summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-03-16 22:07:14 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-03-16 22:07:14 +0000
commit55e3115447817eeb38232f38fc865bfe8403ef9c (patch)
tree4fddfc249ef1bf04db55549bd97195d1e58227d8
parent106d2d8c86bd35ccba6a9f87124742df0d1759d5 (diff)
downloadpx4-nuttx-55e3115447817eeb38232f38fc865bfe8403ef9c.tar.gz
px4-nuttx-55e3115447817eeb38232f38fc865bfe8403ef9c.tar.bz2
px4-nuttx-55e3115447817eeb38232f38fc865bfe8403ef9c.zip
Move common parts of C5471 into drivers/ so it can be used by other platforms.
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@75 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--nuttx/arch/c5471/include/serial.h6
-rw-r--r--nuttx/arch/c5471/src/up_serial.c1112
-rw-r--r--nuttx/drivers/Makefile2
-rw-r--r--nuttx/drivers/serial.c578
-rw-r--r--nuttx/include/nuttx/serial.h241
5 files changed, 1171 insertions, 768 deletions
diff --git a/nuttx/arch/c5471/include/serial.h b/nuttx/arch/c5471/include/serial.h
index 2202a6450..c10fa4269 100644
--- a/nuttx/arch/c5471/include/serial.h
+++ b/nuttx/arch/c5471/include/serial.h
@@ -51,11 +51,7 @@
#define TIOCSERGSTRUCT 0x5403 /* Get up_dev_t for port */
/************************************************************
- * Private Data
- ************************************************************/
-
-/************************************************************
- * Private Functions
+ * Public Data
************************************************************/
/************************************************************
diff --git a/nuttx/arch/c5471/src/up_serial.c b/nuttx/arch/c5471/src/up_serial.c
index 4b70ca4e2..4651b1242 100644
--- a/nuttx/arch/c5471/src/up_serial.c
+++ b/nuttx/arch/c5471/src/up_serial.c
@@ -46,7 +46,7 @@
#include <debug.h>
#include <nuttx/irq.h>
#include <nuttx/arch.h>
-#include <nuttx/fs.h>
+#include <nuttx/serial.h>
#include <arch/serial.h>
#include "c5471.h"
#include "os_internal.h"
@@ -66,30 +66,19 @@
* Private Types
************************************************************/
-/* This is the internal structure for each serial port's state. */
-
struct uart_regs_s
{
uint32 ier;
uint32 lcr;
uint32 fcr;
+#ifdef CONFIG_UART_HWFLOWCONTROL
uint32 efr;
uint32 tcr;
-};
-
-struct uart_buffer_s
-{
- sem_t sem; /* Used to control exclusive access to the buffer */
- sint16 head; /* Index to the head [IN] index in the buffer */
- sint16 tail; /* Index to the tail [OUT] index in the buffer */
- sint16 size; /* The allocated size of the buffer */
- char *buffer; /* Pointer to the allocated buffer memory */
+#endif
};
struct up_dev_s
{
- int open_count; /* The number of times
- * the device has been opened */
unsigned int uartbase; /* Base address of UART
* registers */
unsigned int baud_base; /* Base baud for conversions */
@@ -105,54 +94,57 @@ struct up_dev_s
#endif
boolean stopbits2; /* TRUE: Configure with 2
* stop bits instead of 1 */
- boolean xmitwaiting; /* TRUE: User is waiting
- * for space in xmit.buffer */
- boolean recvwaiting; /* TRUE: User is waiting
- * for space in recv.buffer */
- boolean isconsole; /* TRUE: This is the serial console */
- sem_t closesem; /* Looks out new opens while
- * close is in progress */
- sem_t xmitsem; /* Used to wakeup user waiting
- * for space in xmit.buffer */
- sem_t recvsem; /* Used to wakeup user waiting
- * for sapce in recv.buffer */
- struct uart_buffer_s xmit; /* Describes transmit buffer */
- struct uart_buffer_s recv; /* Describes receive buffer */
struct uart_regs_s regs; /* Shadow copy of readonly regs */
};
-typedef struct up_dev_s up_dev_t;
/************************************************************
* Private Function Prototypes
************************************************************/
-static int up_open(struct file *filep);
-static int up_close(struct file *filep);
-static ssize_t up_read(struct file *filep, char *buffer, size_t buflen);
-static ssize_t up_write(struct file *filep, const char *buffer, size_t buflen);
+static int up_setup(struct uart_dev_s *dev);
+static void up_shutdown(struct uart_dev_s *dev);
+static int up_interrupt(int irq, void *context);
static int up_ioctl(struct file *filep, int cmd, unsigned long arg);
-static void up_uartsetup(up_dev_t *dev);
+static int up_receive(struct uart_dev_s *dev, unsigned int *status);
+static void up_rxint(struct uart_dev_s *dev, boolean enable);
+static boolean up_rxfifonotempty(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, boolean enable);
+static boolean up_txfifonotfull(struct uart_dev_s *dev);
+static boolean up_txfifoempty(struct uart_dev_s *dev);
/************************************************************
* Private Variables
************************************************************/
-struct file_operations g_serialops =
-{
- .open = up_open,
- .close = up_close,
- .read = up_read,
- .write = up_write,
- .ioctl = up_ioctl,
+struct uart_ops_s g_uart_ops =
+{
+ .setup = up_setup,
+ .shutdown = up_shutdown,
+ .handler = up_interrupt,
+ .ioctl = up_ioctl,
+ .receive = up_receive,
+ .rxint = up_rxint,
+ .rxfifonotempty = up_rxfifonotempty,
+ .send = up_send,
+ .txint = up_txint,
+ .txfifonotfull = up_txfifonotfull,
+ .txfifoempty = up_txfifoempty,
};
+/* I/O buffers */
+
+static char g_irdarxbuffer[CONFIG_UART_IRDA_RXBUFSIZE];
+static char g_irdatxbuffer[CONFIG_UART_IRDA_TXBUFSIZE];
+static char g_modemrxbuffer[CONFIG_UART_IRDA_RXBUFSIZE];
+static char g_modemtxbuffer[CONFIG_UART_MODEM_TXBUFSIZE];
+
/* This describes the state of the C5471 serial IRDA port. */
-static up_dev_t g_irdaport =
+static struct up_dev_s g_irdapriv =
{
.xmit_fifo_size = UART_IRDA_XMIT_FIFO_SIZE,
.baud_base = BASE_BAUD,
- .irq = C5471_IRQ_UART_IRDA,
.uartbase = UART_IRDA_BASE,
.baud = CONFIG_UART_IRDA_BAUD,
.parity = CONFIG_UART_IRDA_PARITY,
@@ -163,13 +155,29 @@ static up_dev_t g_irdaport =
.stopbits2 = CONFIG_UART_IRDA_2STOP,
};
+static uart_dev_t g_irdaport =
+{
+ .irq = C5471_IRQ_UART_IRDA,
+ .recv =
+ {
+ .size = CONFIG_UART_IRDA_RXBUFSIZE,
+ .buffer = g_irdarxbuffer,
+ },
+ .xmit =
+ {
+ .size = CONFIG_UART_IRDA_TXBUFSIZE,
+ .buffer = g_irdatxbuffer,
+ },
+ .ops = &g_uart_ops,
+ .priv = &g_irdapriv,
+};
+
/* This describes the state of the C5471 serial Modem port. */
-static up_dev_t g_modemport =
+static struct up_dev_s g_modempriv =
{
.xmit_fifo_size = UART_XMIT_FIFO_SIZE,
.baud_base = BASE_BAUD,
- .irq = C5471_IRQ_UART,
.uartbase = UART_MODEM_BASE,
.baud = CONFIG_UART_MODEM_BAUD,
.parity = CONFIG_UART_MODEM_PARITY,
@@ -180,128 +188,122 @@ static up_dev_t g_modemport =
.stopbits2 = CONFIG_UART_MODEM_2STOP,
};
-/* I/O buffers */
-
-static char g_irdarxbuffer[CONFIG_UART_IRDA_RXBUFSIZE];
-static char g_irdatxbuffer[CONFIG_UART_IRDA_TXBUFSIZE];
-static char g_modemrxbuffer[CONFIG_UART_IRDA_RXBUFSIZE];
-static char g_modemtxbuffer[CONFIG_UART_MODEM_TXBUFSIZE];
+static uart_dev_t g_modemport =
+{
+ .irq = C5471_IRQ_UART,
+ .recv =
+ {
+ .size = CONFIG_UART_MODEM_RXBUFSIZE,
+ .buffer = g_modemrxbuffer,
+ },
+ .xmit =
+ {
+ .size = CONFIG_UART_MODEM_TXBUFSIZE,
+ .buffer = g_modemtxbuffer,
+ },
+ .ops = &g_uart_ops,
+ .priv = &g_modempriv,
+};
/* Now, which one with be tty0/console and which tty1? */
#ifdef CONFIG_SERIAL_IRDA_CONSOLE
# define CONSOLE_DEV g_irdaport
# define TTYS0_DEV g_irdaport
-# define TTYS0_RXBUFFER g_irdarxbuffer
-# define TTYS0_RXBUFSIZE CONFIG_UART_IRDA_RXBUFSIZE
-# define TTYS0_TXBUFFER g_irdatxbuffer
-# define TTYS0_TXBUFSIZE CONFIG_UART_IRDA_TXBUFSIZE
# define TTYS1_DEV g_modemport
-# define TTYS1_RXBUFFER g_modemrxbuffer
-# define TTYS1_RXBUFSIZE CONFIG_UART_MODEM_RXBUFSIZE
-# define TTYS1_TXBUFFER g_modemtxbuffer
-# define TTYS1_TXBUFSIZE CONFIG_UART_MODEM_TXBUFSIZE
#else
# define CONSOLE_DEV g_modemport
# define TTYS0_DEV g_modemport
-# define TTYS0_RXBUFFER g_modemrxbuffer
-# define TTYS0_RXBUFSIZE CONFIG_UART_MODEM_RXBUFSIZE
-# define TTYS0_TXBUFFER g_modemtxbuffer
-# define TTYS0_TXBUFSIZE CONFIG_UART_MODEM_TXBUFSIZE
# define TTYS1_DEV g_irdaport
-# define TTYS1_RXBUFFER g_irdarxbuffer
-# define TTYS1_RXBUFSIZE CONFIG_UART_IRDA_RXBUFSIZE
-# define TTYS1_TXBUFFER g_irdatxbuffer
-# define TTYS1_TXBUFSIZE CONFIG_UART_IRDA_TXBUFSIZE
#endif
/************************************************************
* Private Functions
************************************************************/
-static inline uint32 up_inserial(up_dev_t *dev, uint32 offset)
-{
- return getreg32(dev->uartbase + offset);
-}
+/************************************************************
+ * Name: up_inserial
+ ************************************************************/
-static inline void up_serialout(up_dev_t *dev, uint32 offset, uint32 value)
+static inline uint32 up_inserial(struct up_dev_s *priv, uint32 offset)
{
- putreg32(value, dev->uartbase + offset);
+ return getreg32(priv->uartbase + offset);
}
-static inline void up_serialreset(up_dev_t *dev)
-{
- /* Both the IrDA and MODEM UARTs support RESET and UART mode. */
-
- up_serialout(dev, UART_MDR_OFFS, MDR_RESET_MODE);
- up_delay(5);
- up_serialout(dev, UART_MDR_OFFS, MDR_UART_MODE);
- up_delay(5);
-}
+/************************************************************
+ * Name: up_serialout
+ ************************************************************/
-static inline void up_disabletxint(up_dev_t *dev)
+static inline void up_serialout(struct up_dev_s *priv, uint32 offset, uint32 value)
{
- dev->regs.ier &= ~UART_IER_XmitInt;
- up_serialout(dev, UART_IER_OFFS, dev->regs.ier);
+ putreg32(value, priv->uartbase + offset);
}
-static inline void up_disablerxint(up_dev_t *dev)
-{
- dev->regs.ier &= ~UART_IER_RecvInt;
- up_serialout(dev, UART_IER_OFFS, dev->regs.ier);
-}
+/************************************************************
+ * Name: up_disableuartint
+ ************************************************************/
-static inline void up_enabletxint(up_dev_t *dev)
+static inline void up_disableuartint(struct up_dev_s *priv, uint16 *ier)
{
-#ifndef CONFIG_SUPPRESS_SERIAL_INTS
- dev->regs.ier |= UART_IER_XmitInt;
- up_serialout(dev, UART_IER_OFFS, dev->regs.ier);
-#endif
+ if (ier)
+ {
+ *ier = priv->regs.ier & UART_IER_AllInts;
+ }
+ priv->regs.ier &= ~UART_IER_AllInts;
+ up_serialout(priv, UART_IER_OFFS, priv->regs.ier);
}
-static inline void up_enablerxint(up_dev_t *dev)
-{
-#ifndef CONFIG_SUPPRESS_SERIAL_INTS
- dev->regs.ier |= UART_IER_RecvInt;
- up_serialout(dev, UART_IER_OFFS, dev->regs.ier);
-#endif
-}
+/************************************************************
+ * Name: up_restoreuartint
+ ************************************************************/
-static inline void up_disableuartint(up_dev_t *dev, uint16 *ier)
+static inline void up_restoreuartint(struct up_dev_s *priv, uint16 ier)
{
- *ier = dev->regs.ier & UART_IER_AllInts;
- dev->regs.ier &= ~UART_IER_AllInts;
- up_serialout(dev, UART_IER_OFFS, dev->regs.ier);
+ priv->regs.ier |= ier & (UART_IER_RecvInt|UART_IER_XmitInt);
+ up_serialout(priv, UART_IER_OFFS, priv->regs.ier);
}
-static inline void up_restoreuartint(up_dev_t *dev, uint16 ier)
-{
- dev->regs.ier |= ier & (UART_IER_RecvInt|UART_IER_XmitInt);
- up_serialout(dev, UART_IER_OFFS, dev->regs.ier);
-}
+/************************************************************
+ * Name: up_waittxfifonotfull
+ ************************************************************/
-static inline void up_clearfifos(up_dev_t *dev)
+static inline void up_waittxfifonotfull(struct up_dev_s *priv)
{
- up_serialout(dev, UART_EFR_OFFS, 0x0010); /* Enable fifo control */
- up_serialout(dev, UART_TFCR_OFFS, 0); /* Reset to 0 */
- up_serialout(dev, UART_RFCR_OFFS, UART_FCR_RX_CLR); /* Clear RX fifo */
- up_serialout(dev, UART_TFCR_OFFS, UART_FCR_TX_CLR); /* Clear TX fifo */
- up_serialout(dev, UART_TFCR_OFFS, UART_FCR_FIFO_EN); /* Enable RX/TX fifos */
+ int tmp;
+
+ for (tmp = 1000 ; tmp > 0 ; tmp--)
+ {
+ if ((up_inserial(priv, UART_SSR_OFFS) & UART_SSR_TXFULL) == 0)
+ {
+ break;
+ }
+ }
}
+/************************************************************
+ * Name: up_disablebreaks
+ ************************************************************/
-static inline void up_disablebreaks(up_dev_t *dev)
+static inline void up_disablebreaks(struct up_dev_s *priv)
{
- dev->regs.lcr &= ~UART_LCR_BOC;
- up_serialout(dev, UART_LCR_OFFS, dev->regs.lcr);
+ priv->regs.lcr &= ~UART_LCR_BOC;
+ up_serialout(priv, UART_LCR_OFFS, priv->regs.lcr);
}
-static inline void up_enablebreaks(up_dev_t *dev)
+/************************************************************
+ * Name: up_enablebreaks
+ ************************************************************/
+
+static inline void up_enablebreaks(struct up_dev_s *priv)
{
- dev->regs.lcr |= UART_LCR_BOC;
- up_serialout(dev, UART_LCR_OFFS, dev->regs.lcr);
+ priv->regs.lcr |= UART_LCR_BOC;
+ up_serialout(priv, UART_LCR_OFFS, priv->regs.lcr);
}
-static inline void up_setrate(up_dev_t *dev, unsigned int rate)
+/************************************************************
+ * Name: up_setrate
+ ************************************************************/
+
+static inline void up_setrate(struct up_dev_s *priv, unsigned int rate)
{
uint32 div_bit_rate;
@@ -334,328 +336,146 @@ static inline void up_setrate(up_dev_t *dev, unsigned int rate)
break;
}
- up_serialout(dev, UART_DIV_BIT_RATE_OFFS, div_bit_rate);
-}
-
-static inline void up_setmode(up_dev_t *dev, uint16 mode)
-{
- dev->regs.lcr &= 0xffffffe0; /* clear original field, and... */
- dev->regs.lcr |= (uint32)mode; /* Set new bits in that field. */
- up_serialout(dev, UART_LCR_OFFS, dev->regs.lcr);
-}
-
-static inline void up_setrxtrigger(up_dev_t *dev, uint16 val)
-{
- /* does val need to be shifted to the right spot? */
- dev->regs.fcr = (dev->regs.fcr & 0xffffff3f) | (val & 0xc0);
- up_serialout(dev, UART_RFCR_OFFS, dev->regs.fcr);
-}
-
-static inline void up_settxtrigger(up_dev_t *dev, uint16 val)
-{
- /* does val need to be shifted to the right spot? */
- dev->regs.fcr = (dev->regs.fcr & 0xffffffcf) | (val & 0x30);
- up_serialout(dev, UART_RFCR_OFFS, dev->regs.fcr);
-}
-
-static inline void up_outserialchar(up_dev_t *dev, ubyte val)
-{
- up_serialout(dev, UART_THR_OFFS, val);
+ up_serialout(priv, UART_DIV_BIT_RATE_OFFS, div_bit_rate);
}
-static inline unsigned char up_inserialchar(up_dev_t *dev,
- uint16 *status)
-{
- uint32 rhr;
- uint32 lsr;
-
- /* Next, construct a 16bit status word that
- * uses the high byte to hold the status bits
- * associated with framing,parity,break and
- * a low byte that holds error bits of LSR for
- * conditions such as overflow, etc.
- */
-
- rhr = up_inserial(dev, UART_RHR_OFFS);
- lsr = up_inserial(dev, UART_LSR_OFFS);
-
- *status = (uint16)((rhr & 0x0000ff00) | (lsr & 0x000000ff));
-
- return rhr & 0x000000ff;
-}
-
-static inline int up_errorcondition(uint16 status)
-{
- return status & 0x0782;
-}
-
-static inline int up_parityerror(uint16 status)
-{
- return status & 0x0100;
-}
-
-static inline int up_framingerror(uint16 status)
-{
- return status & 0x0200;
-}
-
-static inline int up_overrunerror(uint16 status)
-{
- return status & 0x0002;
-}
-
-static inline uint32 up_getintcause(up_dev_t *dev)
-{
- return up_inserial(dev, UART_ISR_OFFS) & 0x0000003f;
-}
-
-static inline int up_xmitint(up_dev_t *dev,
- uint32 cause)
-{
- return (cause & 0x00000002) == 0x00000002;
-}
-
-static inline int up_recvint(up_dev_t *dev, uint32 cause)
-{
- return (cause & 0x0000000c) == 0x00000004;
-}
-
-static inline int up_recvtimeoutint(up_dev_t *dev, uint32 cause)
-{
- return (cause & 0x0000000c) == 0x0000000c;
-}
-
-static inline ubyte up_txfifoempty(up_dev_t *dev)
-{
- return (up_inserial(dev, UART_LSR_OFFS) & UART_LSR_TREF) != 0;
-}
+/************************************************************
+ * Name: up_setup
+ *
+ * Description:
+ * Configure the UART baud, bits, parity, fifos, etc. This
+ * method is called the first time that the serial port is
+ * opened.
+ *
+ ************************************************************/
-static inline ubyte up_txfifonotfull(up_dev_t *dev)
+static int up_setup(struct uart_dev_s *dev)
{
- return (up_inserial(dev, UART_SSR_OFFS) & UART_SSR_TXFULL) == 0;
-}
+#ifdef CONFIG_SUPPRESS_UART_CONFIG
+ struct up_dev_s *priv = dev->priv;
+ unsigned int cval;
-static inline void up_waittxfifonotfull(up_dev_t *dev)
-{
- int tmp;
- for (tmp = 1000 ; tmp > 0 ; tmp--)
+ if (priv->bits == 7)
{
- if (up_txfifonotfull(dev))
- {
- break;
- }
+ cval = UART_LCR_7bits;
+ }
+ else
+ {
+ cval = UART_LCR_8bits;
}
-}
-
-static inline ubyte up_rxfifonotempty(up_dev_t *dev)
-{
- return up_inserial(dev, UART_LSR_OFFS) & UART_RX_FIFO_NOEMPTY;
-}
-
-static inline void serial_enable_hw_flow_control(up_dev_t *dev)
-{
- /* Set the FIFO level triggers for flow control
- * Halt = 48 bytes, resume = 12 bytes
- */
-
- dev->regs.tcr = (dev->regs.tcr & 0xffffff00) | 0x0000003c;
- up_serialout(dev, UART_TCR_OFFS, dev->regs.tcr);
- /* Enable RTS/CTS flow control */
+ if (priv->stopbits2)
+ {
+ cval |= UART_LCR_2stop;
+ }
- dev->regs.efr |= 0x000000c0;
- up_serialout(dev, UART_EFR_OFFS, dev->regs.efr);
-}
+ if (priv->parity == 1) /* Odd parity */
+ {
+ cval |= (UART_LCR_ParEn|UART_LCR_ParOdd);
+ }
+ else if (priv->parity == 2) /* Even parity */
+ {
+ cval |= (UART_LCR_ParEn|UART_LCR_ParEven);
+ }
-static inline void serial_disable_hw_flow_control(up_dev_t *dev)
-{
- /* Disable RTS/CTS flow control */
+ /* Both the IrDA and MODEM UARTs support RESET and UART mode. */
- dev->regs.efr &= 0xffffff3f;
- up_serialout(dev, UART_EFR_OFFS, dev->regs.efr);
-}
+ up_serialout(priv, UART_MDR_OFFS, MDR_RESET_MODE);
+ up_delay(5);
+ up_serialout(priv, UART_MDR_OFFS, MDR_UART_MODE);
+ up_delay(5);
-static inline void up_saveregisters(up_dev_t *dev)
-{
- dev->regs.ier = up_inserial(dev, UART_IER_OFFS);
- dev->regs.lcr = up_inserial(dev, UART_LCR_OFFS);
+ priv->regs.ier = up_inserial(priv, UART_IER_OFFS);
+ priv->regs.lcr = up_inserial(priv, UART_LCR_OFFS);
#ifdef CONFIG_UART_HWFLOWCONTROL
- if (dev->flowcontrol)
+ if (priv->flowcontrol)
{
- dev->regs.efr = up_inserial(dev, UART_EFR_OFFS);
- dev->regs.tcr = up_inserial(dev, UART_TCR_OFFS);
+ priv->regs.efr = up_inserial(priv, UART_EFR_OFFS);
+ priv->regs.tcr = up_inserial(priv, UART_TCR_OFFS);
}
#endif
-}
-/************************************************************
- * up_takesem
- ************************************************************/
+ up_disableuartint(priv, NULL);
-static void up_takesem(sem_t *sem)
-{
- while (sem_wait(sem) != 0)
- {
- /* The only case that an error should occur here is if
- * the wait was awakened by a signal.
- */
+ up_serialout(priv, UART_EFR_OFFS, 0x0010); /* Enable fifo control */
+ up_serialout(priv, UART_TFCR_OFFS, 0); /* Reset to 0 */
+ up_serialout(priv, UART_RFCR_OFFS, UART_FCR_RX_CLR); /* Clear RX fifo */
+ up_serialout(priv, UART_TFCR_OFFS, UART_FCR_TX_CLR); /* Clear TX fifo */
+ up_serialout(priv, UART_TFCR_OFFS, UART_FCR_FIFO_EN); /* Enable RX/TX fifos */
- ASSERT(*get_errno_ptr() == EINTR);
- }
-}
+ up_disablebreaks(priv);
-/************************************************************
- * Name: up_givesem
- ************************************************************/
+ priv->regs.fcr = (priv->regs.fcr & 0xffffffcf) | (val & 0x30);
+ up_serialout(priv, UART_RFCR_OFFS, priv->regs.fcr);
-static inline void up_givesem(sem_t *sem)
-{
- (void)sem_post(sem);
-}
+ priv->regs.fcr = (priv->regs.fcr & 0xffffff3f) | (val & 0xc0);
+ up_serialout(priv, UART_RFCR_OFFS, priv->regs.fcr);
-/************************************************************
- * Name: up_receivechars
- ************************************************************/
+ up_setrate(priv, priv->baud);
-/* Add chars to head of receive buffer. up_read will take
- * characters from the tail of the buffer.
- */
-
-static void up_recvchars(up_dev_t *dev)
-{
- uint16 status;
- int nexthead = dev->recv.head + 1;
+ priv->regs.lcr &= 0xffffffe0; /* clear original field, and... */
+ priv->regs.lcr |= (uint32)mode; /* Set new bits in that field. */
+ up_serialout(priv, UART_LCR_OFFS, priv->regs.lcr);
- if (nexthead >= dev->recv.size)
+#ifdef CONFIG_UART_HWFLOWCONTROL
+ if (priv->flowcontrol)
{
- nexthead = 0;
- }
+ /* Set the FIFO level triggers for flow control
+ * Halt = 48 bytes, resume = 12 bytes
+ */
- while (nexthead != dev->recv.tail && up_rxfifonotempty(dev))
- {
- dev->recv.buffer[dev->recv.head] = up_inserialchar(dev, &status);
+ priv->regs.tcr = (priv->regs.tcr & 0xffffff00) | 0x0000003c;
+ up_serialout(priv, UART_TCR_OFFS, priv->regs.tcr);
- dev->recv.head = nexthead;
- if (++nexthead >= dev->recv.size)
- {
- nexthead = 0;
- }
+ /* Enable RTS/CTS flow control */
- if (dev->recvwaiting)
- {
- dev->recvwaiting = FALSE;
- up_givesem(&dev->recvsem);
- }
+ priv->regs.efr |= 0x000000c0;
+ up_serialout(priv, UART_EFR_OFFS, priv->regs.efr);
}
-}
-
-/************************************************************
- * up_xmitchars
- ************************************************************/
-
-/* Transmit characters from the tail of the xmit buffer while
- * up_write adds data to the head of the xmit buffer.
- */
-
-static void up_xmitchars(up_dev_t *dev)
-{
- /* Send while we still have data & room in the fifo */
-
- while (dev->xmit.head != dev->xmit.tail && up_txfifonotfull(dev))
+ else
{
- up_outserialchar(dev, dev->xmit.buffer[dev->xmit.tail]);
-
- if (++(dev->xmit.tail) >= dev->xmit.size)
- {
- dev->xmit.tail = 0;
- }
-
- if (dev->xmitwaiting)
- {
- dev->xmitwaiting = FALSE;
- up_givesem(&dev->xmitsem);
- }
- }
-
- /* When all of the characters have been sent from the buffer
- * disable the TX interrupt.
- */
+ /* Disable RTS/CTS flow control */
- if (dev->xmit.head == dev->xmit.tail)
- {
- up_disabletxint(dev);
+ priv->regs.efr &= 0xffffff3f;
+ up_serialout(priv, UART_EFR_OFFS, priv->regs.efr);
}
+#endif
+#endif
+ return OK;
}
/************************************************************
- * Name: up_putxmitchar
+ * Name: up_shutdown
+ *
+ * Description:
+ * Disable the UART. This method is called when the serial port is closed
+ *
************************************************************/
-static void up_putxmitchar(up_dev_t *dev, int ch)
+static void up_shutdown(struct uart_dev_s *dev)
{
- int nexthead = dev->xmit.head + 1;
- if (nexthead >= dev->xmit.size)
- {
- nexthead = 0;
- }
-
- for(;;)
- {
- if (nexthead != dev->xmit.tail)
- {
- dev->xmit.buffer[dev->xmit.head] = ch;
- dev->xmit.head = nexthead;
- return;
- }
- else
- {
-#if defined(CONFIG_SUPPRESS_INTERRUPTS) || defined(CONFIG_SUPPRESS_SERIAL_INTS)
- /* Transfer some characters with interrupts disabled */
-
- up_xmitchars(dev);
-
- /* If we unsuccessful in making room in the buffer.
- * then transmit the characters with interrupts
- * enabled and wait for result.
- */
-
- if (nexthead == dev->xmit.tail)
- {
- /* Still no space */
-
- up_waittxfifonotfull(dev);
- }
-#else
- /* Inform the interrupt level logic that we are waiting */
-
- dev->xmitwaiting = TRUE;
-
- /* Wait for some characters to be sent from the buffer
- * with the TX interrupt enabled. When the TX interrupt
- * is enabled, up_xmitchars should execute and remove
- * some of the data from the TX buffer.
- */
-
- up_enabletxint(dev);
- up_takesem(&dev->xmitsem);
- up_disabletxint(dev);
-#endif
- }
- }
+ struct up_dev_s *priv = (struct up_dev_s*)CONSOLE_DEV.priv;
+ up_disableuartint(priv, NULL);
}
/************************************************************
* Name: up_interrupt
+ *
+ * Description:
+ * This is the UART interrupt handler. It will be invoked
+ * when an interrupt received on the 'irq' It should call
+ * uart_transmitchars or uart_receivechar to perform the
+ * appropriate data transfers. The interrupt handling logic\
+ * must be able to map the 'irq' number into the approprite
+ * uart_dev_s structure in order to call these functions.
+ *
************************************************************/
-/* This routine is used to handle the "top half" processing for the
- * serial driver.
- */
-
static int up_interrupt(int irq, void *context)
{
- up_dev_t *dev;
- volatile uint32 cause;
+ struct uart_dev_s *dev = NULL;
+ struct up_dev_s *priv;
+ volatile uint32 cause;
if (g_irdaport.irq == irq)
{
@@ -669,10 +489,11 @@ static int up_interrupt(int irq, void *context)
{
PANIC(OSERR_INTERNAL);
}
+ priv = (struct up_dev_s*)dev->priv;
- cause = up_getintcause(dev);
+ cause = up_inserial(priv, UART_ISR_OFFS) & 0x0000003f;
- if (up_recvtimeoutint(dev, cause))
+ if ((cause & 0x0000000c) == 0x0000000c)
{
uint32 ier_val = 0;
@@ -685,19 +506,19 @@ static int up_interrupt(int irq, void *context)
* below.
*/
- ier_val = up_inserial(dev, UART_IER_OFFS);
+ ier_val = up_inserial(priv, UART_IER_OFFS);
/* Then disable all IrDA UART interrupts */
- up_serialout(dev, UART_IER_OFFS, 0);
+ up_serialout(priv, UART_IER_OFFS, 0);
}
/* Receive characters from the RX fifo */
- up_recvchars(dev);
+ uart_recvchars(dev);
/* read UART_RHR to clear int condition
- * toss = up_inserialchar(dev,&status);
+ * toss = up_inserialchar(priv,&status);
*/
/* Is this an interrupt from the IrDA UART? */
@@ -706,261 +527,42 @@ static int up_interrupt(int irq, void *context)
{
/* Restore the IrDA UART interrupt enables */
- up_serialout(dev, UART_IER_OFFS, ier_val);
+ up_serialout(priv, UART_IER_OFFS, ier_val);
}
}
- else if (up_recvint(dev, cause))
+ else if ((cause & 0x0000000c) == 0x00000004)
{
- up_recvchars(dev);
+ uart_recvchars(dev);
}
- if (up_xmitint(dev, cause))
+ if ((cause & 0x00000002) != 0)
{
- up_xmitchars(dev);
+ uart_xmitchars(dev);
}
return OK;
}
/************************************************************
- * Name: up_uartsetup
- ************************************************************/
-
-static void up_uartsetup(up_dev_t *dev)
-{
-#ifdef CONFIG_SUPPRESS_UART_CONFIG
- unsigned int cval;
- uint16 mrs;
-
- if (dev->bits == 7)
- {
- cval = UART_LCR_7bits;
- }
- else
- {
- cval = UART_LCR_8bits;
- }
-
- if (dev->stopbits2)
- {
- cval |= UART_LCR_2stop;
- }
-
- if (dev->parity == 1) /* Odd parity */
- {
- cval |= (UART_LCR_ParEn|UART_LCR_ParOdd);
- }
- else if (dev->parity == 2) /* Even parity */
- {
- cval |= (UART_LCR_ParEn|UART_LCR_ParEven);
- }
-
- up_serialreset(dev);
- up_saveregisters(dev);
- up_disableuartint(dev, &mrs);
- up_clearfifos(dev);
- up_disablebreaks(dev);
- up_settxtrigger(dev, UART_FCR_FTL);
- up_setrxtrigger(dev, UART_FCR_FTL);
- up_setrate(dev, dev->baud);
- up_setmode(dev, cval);
-
-#ifdef CONFIG_UART_HWFLOWCONTROL
- if (dev->flowcontrol)
- {
- serial_enable_hw_flow_control(dev);
- }
- else
-#endif
- {
- serial_disable_hw_flow_control(dev);
- }
-#endif
-}
-
-/************************************************************
- * shutdown
- ************************************************************/
-
-/* This routine will shutdown a serial port; interrupts are disabled, and
- * DTR is dropped if the hangup on close termio flag is on.
- */
-
-static void shutdown(up_dev_t * dev)
-{
- irqstate_t flags;
- uint16 msr;
-
- /* Free the IRQ */
-
- flags = irqsave(); /* Disable interrupts */
- up_disable_irq(dev->irq);
- irq_detach(dev->irq);
- up_disableuartint(dev, &msr);
- irqrestore(flags);
-}
-
-/************************************************************
- * Name: up_irqwrite
- ************************************************************/
-
-static ssize_t up_irqwrite(up_dev_t *dev, const char *buffer, size_t buflen)
-{
- ssize_t ret = buflen;
-
- /* Force each character through the low level interface */
-
- for (; buflen; buflen--)
- {
- int ch = *buffer++;
- up_lowputc(ch);
-
- /* If this is the console, then we should replace LF with LF-CR */
-
- if (ch == '\n')
- {
- up_lowputc('\r');
- }
- }
-
- return ret;
-}
-
-/************************************************************
- * Name: up_write
- ************************************************************/
-
-static ssize_t up_write(struct file *filep, const char *buffer, size_t buflen)
-{
- struct inode *inode = filep->f_inode;
- up_dev_t *dev = inode->i_private;
- ssize_t ret = buflen;
-
- /* We may receive console writes through this path from
- * interrupt handlers and from debug output in the IDLE task!
- * In these cases, we will need to do things a little
- * differently.
- */
-
- if (up_interrupt_context() || getpid() == 0)
- {
- if (dev->isconsole)
- {
- irqstate_t flags = irqsave();
- ret = up_irqwrite(dev, buffer, buflen);
- irqrestore(flags);
- return ret;
- }
- else
- {
- return ERROR;
- }
- }
-
- /* Only one user can be accessing dev->xmit.head at once */
-
- up_takesem(&dev->xmit.sem);
-
- /* Loop while we still have data to copy to the transmit buffer.
- * we add data to the head of the buffer; up_xmitchars takes the
- * data from the end of the buffer.
- */
-
- up_disabletxint(dev);
- for (; buflen; buflen--)
- {
- int ch = *buffer++;
-
- /* Put the character into the transmit buffer */
-
- up_putxmitchar(dev, ch);
-
- /* If this is the console, then we should replace LF with LF-CR */
-
- if (dev->isconsole && ch == '\n')
- {
- up_putxmitchar(dev, '\r');
- }
- }
-
- if (dev->xmit.head != dev->xmit.tail)
- {
-#if defined(CONFIG_SUPPRESS_INTERRUPTS) || defined(CONFIG_SUPPRESS_SERIAL_INTS)
- up_xmitchars(dev);
-#else
- up_enabletxint(dev);
-#endif
- }
-
- up_givesem(&dev->xmit.sem);
- return ret;
-}
-
-/************************************************************
- * Name: up_read
- ************************************************************/
-
-static ssize_t up_read(struct file *filep, char *buffer, size_t buflen)
-{
- struct inode *inode = filep->f_inode;
- up_dev_t *dev = inode->i_private;
- ssize_t ret = buflen;
-
- /* Only one user can be accessing dev->recv.tail at once */
-
- up_takesem(&dev->recv.sem);
-
- /* Loop while we still have data to copy to the receive buffer.
- * we add data to the head of the buffer; up_xmitchars takes the
- * data from the end of the buffer.
- */
-
- up_disablerxint(dev);
- while (buflen)
- {
- if (dev->recv.head != dev->recv.tail)
- {
- *buffer++ = dev->recv.buffer[dev->recv.tail];
- buflen--;
-
- if (++(dev->recv.tail) >= dev->recv.size)
- {
- dev->recv.tail = 0;
- }
- }
- else
- {
- /* Wait for some characters to be sent from the buffer
- * with the TX interrupt disabled.
- */
-
- dev->recvwaiting = TRUE;
- up_enablerxint(dev);
- up_takesem(&dev->recvsem);
- up_disablerxint(dev);
- }
- }
-
- up_enablerxint(dev);
- up_givesem(&dev->recv.sem);
- return ret;
-}
-
-/************************************************************
* Name: up_ioctl
+ *
+ * Description:
+ * All ioctl calls will be routed through this method
+ *
************************************************************/
static int up_ioctl(struct file *filep, int cmd, unsigned long arg)
{
- struct inode *inode = filep->f_inode;
- up_dev_t *dev = inode->i_private;
- int ret = OK;
+ struct inode *inode = filep->f_inode;
+ struct uart_dev_s *dev = inode->i_private;
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ int ret = OK;
switch (cmd)
{
case TIOCSERGSTRUCT:
{
- up_dev_t *user = (up_dev_t*)arg;
+ struct up_dev_s *user = (struct up_dev_s*)arg;
if (!user)
{
*get_errno_ptr() = EINVAL;
@@ -968,7 +570,7 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg)
}
else
{
- memcpy(user, dev, sizeof(up_dev_t));
+ memcpy(user, dev, sizeof(struct up_dev_s));
}
}
break;
@@ -976,7 +578,7 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg)
case TIOCSBRK: /* BSD compatibility: Turn break on, unconditionally */
{
irqstate_t flags = irqsave();
- up_enablebreaks(dev);
+ up_enablebreaks(priv);
irqrestore(flags);
}
break;
@@ -985,7 +587,7 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg)
{
irqstate_t flags;
flags = irqsave();
- up_disablebreaks(dev);
+ up_disablebreaks(priv);
irqrestore(flags);
}
break;
@@ -1000,146 +602,139 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg)
}
/************************************************************
- * Name: up_close
+ * Name: up_receive
*
* Description:
- * This routine is called when the serial port gets closed.
- * It waits for the last remaining data to be sent.
+ * Called (usually) from the interrupt level to receive one character from
+ * the UART. Error bits associated with the receipt are provided in the
+ * the return 'status'.
*
************************************************************/
-static int up_close(struct file *filep)
+static int up_receive(struct uart_dev_s *dev, unsigned int *status)
{
- struct inode *inode = filep->f_inode;
- up_dev_t *dev = inode->i_private;
-
- up_takesem(&dev->closesem);
- if (dev->open_count > 1)
- {
- dev->open_count--;
- up_givesem(&dev->closesem);
- return OK;
- }
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ uint32 rhr;
+ uint32 lsr;
- /* There are no more references to the port */
+ /* Construct a 16bit status word that uses the high byte to
+ * hold the status bits associated with framing,parity,break
+ * and a low byte that holds error bits of LSR for
+ * conditions such as overflow, etc.
+ */
- dev->open_count = 0;
+ rhr = up_inserial(priv, UART_RHR_OFFS);
+ lsr = up_inserial(priv, UART_LSR_OFFS);
- /* Stop accepting input */
+ *status = (unsigned int)((rhr & 0x0000ff00) | (lsr & 0x000000ff));
- up_disablerxint(dev);
+ return rhr & 0x000000ff;
+}
- /* Now we wait for the transmit buffer to clear */
+/************************************************************
+ * Name: up_rxint
+ *
+ * Description:
+ * Call to enable or disable RX interrupts
+ *
+ ************************************************************/
- while (dev->xmit.head != dev->xmit.tail)
+static void up_rxint(struct uart_dev_s *dev, boolean enable)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ if (enable)
{
- usleep(500*1000);
+#ifndef CONFIG_SUPPRESS_SERIAL_INTS
+ priv->regs.ier |= UART_IER_RecvInt;
+ up_serialout(priv, UART_IER_OFFS, priv->regs.ier);
+#endif
}
-
- /* And wait for the TX fifo to drain */
-
- while (!up_txfifoempty(dev))
+ else
{
- usleep(500*1000);
+ priv->regs.ier &= ~UART_IER_RecvInt;
+ up_serialout(priv, UART_IER_OFFS, priv->regs.ier);
}
-
- /* That's it! */
-
- shutdown(dev);
- up_givesem(&dev->closesem);
- return OK;
- }
+}
/************************************************************
- * Name: up_open
+ * Name: up_rxfifonotempty
*
* Description:
- * This routine is called whenever a serial port is opened.
+ * Return TRUE if the receive fifo is not empty
*
************************************************************/
-static int up_open(struct file *filep)
+static boolean up_rxfifonotempty(struct uart_dev_s *dev)
{
- struct inode *inode = filep->f_inode;
- up_dev_t *dev = inode->i_private;
- int ret = OK;
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ return up_inserial(priv, UART_LSR_OFFS) & UART_RX_FIFO_NOEMPTY;
+}
- /* If the port is the middle of closing, wait until the close
- * is finished
- */
+/************************************************************
+ * Name: up_send
+ *
+ * Description:
+ * This method will send one byte on the UART
+ *
+ ************************************************************/
- up_takesem(&dev->closesem);
+static void up_send(struct uart_dev_s *dev, int ch)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ up_serialout(priv, UART_THR_OFFS, (ubyte)ch);
+}
- /* Start up serial port */
+/************************************************************
+ * Name: up_txint
+ *
+ * Description:
+ * Call to enable or disable TX interrupts
+ *
+ ************************************************************/
- if (++dev->open_count == 1)
+static void up_txint(struct uart_dev_s *dev, boolean enable)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ if (enable)
{
- irqstate_t flags = irqsave();
-
- /* If this is the console, then the UART has already
- * been initialized.
- */
-
- if (!dev->isconsole)
- {
- up_uartsetup(dev);
- }
-
- /* But, in any event, we do have to configure for
- * interrupt driven mode of operation.
- */
-
- /* Attache and enabled the IRQ */
-
#ifndef CONFIG_SUPPRESS_SERIAL_INTS
- ret = irq_attach(dev->irq, up_interrupt);
- if (ret == OK)
+ priv->regs.ier |= UART_IER_XmitInt;
+ up_serialout(priv, UART_IER_OFFS, priv->regs.ier);
#endif
- {
- /* Mark the io buffers empty */
-
- dev->xmit.head = 0;
- dev->xmit.tail = 0;
- dev->recv.head = 0;
- dev->recv.tail = 0;
-
- /* Finally, enable interrupts */
-
-#ifndef CONFIG_SUPPRESS_SERIAL_INTS
- up_enable_irq(dev->irq);
-#endif
- up_enablerxint(dev);
- }
- irqrestore(flags);
}
-
- up_givesem(&dev->closesem);
- return ret;
+ else
+ {
+ priv->regs.ier &= ~UART_IER_XmitInt;
+ up_serialout(priv, UART_IER_OFFS, priv->regs.ier);
+ }
}
/************************************************************
- * Name: up_devinit
+ * Name: up_txfifonotfull
+ *
+ * Description:
+ * Return TRUE if the tranmsit fifo is not full
+ *
************************************************************/
-static void up_devinit(up_dev_t *dev,
- char *rxbuffer, int rxbufsize,
- char *txbuffer, int txbufsize)
+static boolean up_txfifonotfull(struct uart_dev_s *dev)
{
- /* Initialize fields in the dev structure that were not
- * statically initialized.
- */
-
- sem_init(&dev->xmit.sem, 0, 1);
- dev->xmit.size = txbufsize;
- dev->xmit.buffer = txbuffer;
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ return (up_inserial(priv, UART_SSR_OFFS) & UART_SSR_TXFULL) == 0;
+}
- sem_init(&dev->recv.sem, 0, 1);
- dev->recv.size = rxbufsize;
- dev->recv.buffer = rxbuffer;
+/************************************************************
+ * Name: up_txfifoempty
+ *
+ * Description:
+ * Return TRUE if the transmit fifo is empty
+ *
+ ************************************************************/
- sem_init(&dev->closesem, 0, 1);
- sem_init(&dev->xmitsem, 0, 0);
- sem_init(&dev->recvsem, 0, 0);
+static boolean up_txfifoempty(struct uart_dev_s *dev)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ return (up_inserial(priv, UART_LSR_OFFS) & UART_LSR_TREF) != 0;
}
/************************************************************
@@ -1158,19 +753,11 @@ static void up_devinit(up_dev_t *dev,
void up_earlyserialinit(void)
{
- /* Set up default port setings */
-
- up_devinit(&TTYS0_DEV,
- TTYS0_RXBUFFER, TTYS0_RXBUFSIZE,
- TTYS0_TXBUFFER, TTYS0_TXBUFSIZE);
- up_devinit(&TTYS1_DEV,
- TTYS1_RXBUFFER, TTYS1_RXBUFSIZE,
- TTYS1_TXBUFFER, TTYS1_TXBUFSIZE);
-
- /* Configure the console for use now */
+ up_disableuartint(TTYS0_DEV.priv, NULL);
+ up_disableuartint(TTYS1_DEV.priv, NULL);
CONSOLE_DEV.isconsole = TRUE;
- up_uartsetup(&CONSOLE_DEV);
+ up_setup(&CONSOLE_DEV);
}
/************************************************************
@@ -1184,9 +771,9 @@ void up_earlyserialinit(void)
void up_serialinit(void)
{
- (void)register_inode("/dev/console", &g_serialops, 0666, &CONSOLE_DEV);
- (void)register_inode("/dev/ttyS0", &g_serialops, 0666, &TTYS0_DEV);
- (void)register_inode("/dev/ttyS1", &g_serialops, 0666, &TTYS1_DEV);
+ (void)uart_register("/dev/console", &CONSOLE_DEV);
+ (void)uart_register("/dev/ttyS0", &TTYS0_DEV);
+ (void)uart_register("/dev/ttyS1", &TTYS1_DEV);
}
/************************************************************
@@ -1200,11 +787,12 @@ void up_serialinit(void)
int up_putc(int ch)
{
+ struct up_dev_s *priv = (struct up_dev_s*)CONSOLE_DEV.priv;
uint16 ier;
- up_disableuartint(&CONSOLE_DEV, &ier);
- up_waittxfifonotfull(&CONSOLE_DEV);
- up_outserialchar(&CONSOLE_DEV, ch);
+ up_disableuartint(priv, &ier);
+ up_waittxfifonotfull(priv);
+ up_serialout(priv, UART_THR_OFFS, (ubyte)ch);
/* Check for LF */
@@ -1212,12 +800,12 @@ int up_putc(int ch)
{
/* Add CR */
- up_waittxfifonotfull(&CONSOLE_DEV);
- up_outserialchar(&CONSOLE_DEV, '\r');
+ up_waittxfifonotfull(priv);
+ up_serialout(priv, UART_THR_OFFS, '\r');
}
- up_waittxfifonotfull(&CONSOLE_DEV);
- up_restoreuartint(&CONSOLE_DEV, ier);
+ up_waittxfifonotfull(priv);
+ up_restoreuartint(priv, ier);
return ch;
}
diff --git a/nuttx/drivers/Makefile b/nuttx/drivers/Makefile
index 8d687a67c..f992f5837 100644
--- a/nuttx/drivers/Makefile
+++ b/nuttx/drivers/Makefile
@@ -40,7 +40,7 @@ MKDEP = $(TOPDIR)/tools/mkdeps.sh
ASRCS =
AOBJS = $(ASRCS:.S=$(OBJEXT))
-CSRCS = dev_null.c
+CSRCS = dev_null.c serial.c
COBJS = $(CSRCS:.c=$(OBJEXT))
SRCS = $(ASRCS) $(CSRCS)
diff --git a/nuttx/drivers/serial.c b/nuttx/drivers/serial.c
new file mode 100644
index 000000000..fd0e5b1b7
--- /dev/null
+++ b/nuttx/drivers/serial.c
@@ -0,0 +1,578 @@
+/************************************************************************************
+ * serial.c
+ *
+ * Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name Gregory Nutt nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************************/
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <semaphore.h>
+#include <string.h>
+#include <errno.h>
+#include <debug.h>
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <nuttx/fs.h>
+#include <nuttx/serial.h>
+
+/************************************************************************************
+ * Definitions
+ ************************************************************************************/
+
+#ifdef CONFIG_HAVE_LOWPUTC
+# define uart_putc(ch) up_lowputc(ch);
+#else
+# define uart_putc(ch) up_putc(ch);
+#endif
+
+/************************************************************************************
+ * Private Types
+ ************************************************************************************/
+
+/************************************************************************************
+ * Private Function Prototypes
+ ************************************************************************************/
+
+static int uart_open(struct file *filep);
+static int uart_close(struct file *filep);
+static ssize_t uart_read(struct file *filep, char *buffer, size_t buflen);
+static ssize_t uart_write(struct file *filep, const char *buffer, size_t buflen);
+static int uart_ioctl(struct file *filep, int cmd, unsigned long arg);
+
+/************************************************************************************
+ * Private Variables
+ ************************************************************************************/
+
+struct file_operations g_serialops =
+{
+ uart_open, /* open */
+ uart_close, /* close */
+ uart_read, /* read */
+ uart_write, /* write */
+ uart_ioctl /* ioctl */
+};
+
+/************************************************************************************
+ * Private Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: uart_waittxfifonotfull
+ ************************************************************************************/
+
+#if defined(CONFIG_SUPPRESS_INTERRUPTS) || defined(CONFIG_SUPPRESS_SERIAL_INTS)
+static inline void uart_waittxfifonotfull(uart_dev_t *dev)
+{
+ int tmp;
+ for (tmp = 1000 ; tmp > 0 ; tmp--)
+ {
+ if (uart_txfifonotfull(dev))
+ {
+ break;
+ }
+ }
+}
+#endif
+
+/************************************************************************************
+ * Name: uart_takesem
+ ************************************************************************************/
+
+static void uart_takesem(sem_t *sem)
+{
+ while (sem_wait(sem) != 0)
+ {
+ /* The only case that an error should occur here is if
+ * the wait was awakened by a signal.
+ */
+
+ ASSERT(*get_errno_ptr() == EINTR);
+ }
+}
+
+/************************************************************************************
+ * Name: uart_givesem
+ ************************************************************************************/
+
+static inline void uart_givesem(sem_t *sem)
+{
+ (void)sem_post(sem);
+}
+
+/************************************************************************************
+ * Name: uart_putxmitchar
+ ************************************************************************************/
+
+static void uart_putxmitchar(uart_dev_t *dev, int ch)
+{
+ int nexthead = dev->xmit.head + 1;
+ if (nexthead >= dev->xmit.size)
+ {
+ nexthead = 0;
+ }
+
+ for(;;)
+ {
+ if (nexthead != dev->xmit.tail)
+ {
+ dev->xmit.buffer[dev->xmit.head] = ch;
+ dev->xmit.head = nexthead;
+ return;
+ }
+ else
+ {
+#if defined(CONFIG_SUPPRESS_INTERRUPTS) || defined(CONFIG_SUPPRESS_SERIAL_INTS)
+ /* Transfer some characters with interrupts disabled */
+
+ uart_xmitchars(dev);
+
+ /* If we unsuccessful in making room in the buffer.
+ * then transmit the characters with interrupts
+ * enabled and wait for result.
+ */
+
+ if (nexthead == dev->xmit.tail)
+ {
+ /* Still no space */
+
+ uart_waittxfifonotfull(dev);
+ }
+#else
+ /* Inform the interrupt level logic that we are waiting */
+
+ dev->xmitwaiting = TRUE;
+
+ /* Wait for some characters to be sent from the buffer
+ * with the TX interrupt enabled. When the TX interrupt
+ * is enabled, uart_xmitchars should execute and remove
+ * some of the data from the TX buffer.
+ */
+
+ uart_enabletxint(dev);
+ uart_takesem(&dev->xmitsem);
+ uart_disabletxint(dev);
+#endif
+ }
+ }
+}
+
+/************************************************************************************
+ * Name: uart_irqwrite
+ ************************************************************************************/
+
+static ssize_t uart_irqwrite(uart_dev_t *dev, const char *buffer, size_t buflen)
+{
+ ssize_t ret = buflen;
+
+ /* Force each character through the low level interface */
+
+ for (; buflen; buflen--)
+ {
+ int ch = *buffer++;
+ uart_putc(ch);
+
+ /* If this is the console, then we should replace LF with LF-CR */
+
+ if (ch == '\n')
+ {
+ uart_putc('\r');
+ }
+ }
+
+ return ret;
+}
+
+/************************************************************************************
+ * Name: uart_write
+ ************************************************************************************/
+
+static ssize_t uart_write(struct file *filep, const char *buffer, size_t buflen)
+{
+ struct inode *inode = filep->f_inode;
+ uart_dev_t *dev = inode->i_private;
+ ssize_t ret = buflen;
+
+ /* We may receive console writes through this path from
+ * interrupt handlers and from debug output in the IDLE task!
+ * In these cases, we will need to do things a little
+ * differently.
+ */
+
+ if (up_interrupt_context() || getpid() == 0)
+ {
+ if (dev->isconsole)
+ {
+ irqstate_t flags = irqsave();
+ ret = uart_irqwrite(dev, buffer, buflen);
+ irqrestore(flags);
+ return ret;
+ }
+ else
+ {
+ return ERROR;
+ }
+ }
+
+ /* Only one user can be accessing dev->xmit.head at once */
+
+ uart_takesem(&dev->xmit.sem);
+
+ /* Loop while we still have data to copy to the transmit buffer.
+ * we add data to the head of the buffer; uart_xmitchars takes the
+ * data from the end of the buffer.
+ */
+
+ uart_disabletxint(dev);
+ for (; buflen; buflen--)
+ {
+ int ch = *buffer++;
+
+ /* Put the character into the transmit buffer */
+
+ uart_putxmitchar(dev, ch);
+
+ /* If this is the console, then we should replace LF with LF-CR */
+
+ if (dev->isconsole && ch == '\n')
+ {
+ uart_putxmitchar(dev, '\r');
+ }
+ }
+
+ if (dev->xmit.head != dev->xmit.tail)
+ {
+#if defined(CONFIG_SUPPRESS_INTERRUPTS) || defined(CONFIG_SUPPRESS_SERIAL_INTS)
+ uart_xmitchars(dev);
+#else
+ uart_enabletxint(dev);
+#endif
+ }
+
+ uart_givesem(&dev->xmit.sem);
+ return ret;
+}
+
+/************************************************************************************
+ * Name: uart_read
+ ************************************************************************************/
+
+static ssize_t uart_read(struct file *filep, char *buffer, size_t buflen)
+{
+ struct inode *inode = filep->f_inode;
+ uart_dev_t *dev = inode->i_private;
+ ssize_t ret = buflen;
+
+ /* Only one user can be accessing dev->recv.tail at once */
+
+ uart_takesem(&dev->recv.sem);
+
+ /* Loop while we still have data to copy to the receive buffer.
+ * we add data to the head of the buffer; uart_xmitchars takes the
+ * data from the end of the buffer.
+ */
+
+ uart_disablerxint(dev);
+ while (buflen)
+ {
+ if (dev->recv.head != dev->recv.tail)
+ {
+ *buffer++ = dev->recv.buffer[dev->recv.tail];
+ buflen--;
+
+ if (++(dev->recv.tail) >= dev->recv.size)
+ {
+ dev->recv.tail = 0;
+ }
+ }
+ else
+ {
+ /* Wait for some characters to be sent from the buffer
+ * with the TX interrupt disabled.
+ */
+
+ dev->recvwaiting = TRUE;
+ uart_enablerxint(dev);
+ uart_takesem(&dev->recvsem);
+ uart_disablerxint(dev);
+ }
+ }
+
+ uart_enablerxint(dev);
+ uart_givesem(&dev->recv.sem);
+ return ret;
+}
+
+/************************************************************************************
+ * Name: uart_ioctl
+ ************************************************************************************/
+
+static int uart_ioctl(struct file *filep, int cmd, unsigned long arg)
+{
+ struct inode *inode = filep->f_inode;
+ uart_dev_t *dev = inode->i_private;
+
+ return dev->ops->ioctl(filep, cmd, arg);
+}
+
+/************************************************************************************
+ * Name: uart_close
+ *
+ * Description:
+ * This routine is called when the serial port gets closed.
+ * It waits for the last remaining data to be sent.
+ *
+ ************************************************************************************/
+
+static int uart_close(struct file *filep)
+{
+ struct inode *inode = filep->f_inode;
+ uart_dev_t *dev = inode->i_private;
+ irqstate_t flags;
+
+ uart_takesem(&dev->closesem);
+ if (dev->open_count > 1)
+ {
+ dev->open_count--;
+ uart_givesem(&dev->closesem);
+ return OK;
+ }
+
+ /* There are no more references to the port */
+
+ dev->open_count = 0;
+
+ /* Stop accepting input */
+
+ uart_disablerxint(dev);
+
+ /* Now we wait for the transmit buffer to clear */
+
+ while (dev->xmit.head != dev->xmit.tail)
+ {
+ usleep(500*1000);
+ }
+
+ /* And wait for the TX fifo to drain */
+
+ while (!uart_txfifoempty(dev))
+ {
+ usleep(500*1000);
+ }
+
+ /* Free the IRQ and disable the UART */
+
+ flags = irqsave(); /* Disable interrupts */
+ up_disable_irq(dev->irq);
+ irq_detach(dev->irq);
+ uart_shutdown(dev);
+ irqrestore(flags);
+
+ uart_givesem(&dev->closesem);
+ return OK;
+ }
+
+/************************************************************************************
+ * Name: uart_open
+ *
+ * Description:
+ * This routine is called whenever a serial port is opened.
+ *
+ ************************************************************************************/
+
+static int uart_open(struct file *filep)
+{
+ struct inode *inode = filep->f_inode;
+ uart_dev_t *dev = inode->i_private;
+ int ret = OK;
+
+ /* If the port is the middle of closing, wait until the close
+ * is finished
+ */
+
+ uart_takesem(&dev->closesem);
+
+ /* Start up serial port */
+
+ if (++dev->open_count == 1)
+ {
+ irqstate_t flags = irqsave();
+
+ /* If this is the console, then the UART has already
+ * been initialized.
+ */
+
+ if (!dev->isconsole)
+ {
+ uart_setup(dev);
+ }
+
+ /* But, in any event, we do have to configure for
+ * interrupt driven mode of operation.
+ */
+
+ /* Attache and enabled the IRQ */
+
+#ifndef CONFIG_SUPPRESS_SERIAL_INTS
+ ret = irq_attach(dev->irq, dev->ops->handler);
+ if (ret == OK)
+#endif
+ {
+ /* Mark the io buffers empty */
+
+ dev->xmit.head = 0;
+ dev->xmit.tail = 0;
+ dev->recv.head = 0;
+ dev->recv.tail = 0;
+
+ /* Finally, enable interrupts */
+
+#ifndef CONFIG_SUPPRESS_SERIAL_INTS
+ up_enable_irq(dev->irq);
+#endif
+ uart_enablerxint(dev);
+ }
+ irqrestore(flags);
+ }
+
+ uart_givesem(&dev->closesem);
+ return ret;
+}
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: uart_register
+ *
+ * Description:
+ * Register serial console and serial ports.
+ *
+ ************************************************************************************/
+
+int uart_register(const char *path, uart_dev_t *dev)
+{
+ sem_init(&dev->xmit.sem, 0, 1);
+ sem_init(&dev->recv.sem, 0, 1);
+ sem_init(&dev->closesem, 0, 1);
+ sem_init(&dev->xmitsem, 0, 0);
+ sem_init(&dev->recvsem, 0, 0);
+
+ dbg("Registering %s\n", path);
+ return register_inode(path, &g_serialops, 0666, dev);
+}
+
+/************************************************************************************
+ * Name: uart_xmitchars
+ *
+ * Description:
+ * This function is called from the UART interrupt handler when an interrupt
+ * is received indicating that there is more space in the transmit FIFO. This
+ * function will send characters from the tail of the xmit buffer while the driver
+ * write() logic adds data to the head of the xmit buffer.
+ *
+ ************************************************************************************/
+
+void uart_xmitchars(uart_dev_t *dev)
+{
+ /* Send while we still have data & room in the fifo */
+
+ while (dev->xmit.head != dev->xmit.tail && uart_txfifonotfull(dev))
+ {
+ uart_send(dev, dev->xmit.buffer[dev->xmit.tail]);
+
+ if (++(dev->xmit.tail) >= dev->xmit.size)
+ {
+ dev->xmit.tail = 0;
+ }
+
+ if (dev->xmitwaiting)
+ {
+ dev->xmitwaiting = FALSE;
+ uart_givesem(&dev->xmitsem);
+ }
+ }
+
+ /* When all of the characters have been sent from the buffer
+ * disable the TX interrupt.
+ */
+
+ if (dev->xmit.head == dev->xmit.tail)
+ {
+ uart_disabletxint(dev);
+ }
+}
+
+/************************************************************************************
+ * Name: uart_receivechars
+ *
+ * Description:
+ * This function is called from the UART interrupt handler when an interrupt
+ * is received indicating that are bytes available in the receive fifo. This
+ * function will add chars to head of receive buffer. Driver read() logic will take
+ * characters from the tail of the buffer.
+ *
+ ************************************************************************************/
+
+void uart_recvchars(uart_dev_t *dev)
+{
+ unsigned int status;
+ int nexthead = dev->recv.head + 1;
+
+ if (nexthead >= dev->recv.size)
+ {
+ nexthead = 0;
+ }
+
+ while (nexthead != dev->recv.tail && uart_rxfifonotempty(dev))
+ {
+ dev->recv.buffer[dev->recv.head] = uart_receive(dev, &status);
+
+ dev->recv.head = nexthead;
+ if (++nexthead >= dev->recv.size)
+ {
+ nexthead = 0;
+ }
+
+ if (dev->recvwaiting)
+ {
+ dev->recvwaiting = FALSE;
+ uart_givesem(&dev->recvsem);
+ }
+ }
+}
+
diff --git a/nuttx/include/nuttx/serial.h b/nuttx/include/nuttx/serial.h
new file mode 100644
index 000000000..7719fca6b
--- /dev/null
+++ b/nuttx/include/nuttx/serial.h
@@ -0,0 +1,241 @@
+/************************************************************************************
+ * serial.h
+ *
+ * Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name Gregory Nutt nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************************/
+
+#ifndef __SERIAL_H
+#define __SERIAL_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+#include <semaphore.h>
+#include <nuttx/fs.h>
+
+/************************************************************************************
+ * Definitions
+ ************************************************************************************/
+
+#define uart_setup(dev) dev->ops->setup(dev)
+#define uart_shutdown(dev) dev->ops->shutdown(dev)
+#define uart_enabletxint(dev) dev->ops->txint(dev, TRUE)
+#define uart_disabletxint(dev) dev->ops->txint(dev, FALSE)
+#define uart_enablerxint(dev) dev->ops->rxint(dev, TRUE)
+#define uart_disablerxint(dev) dev->ops->rxint(dev, FALSE)
+#define uart_rxfifonotempty(dev) dev->ops->rxfifonotempty(dev)
+#define uart_txfifonotfull(dev) dev->ops->txfifonotfull(dev)
+#define uart_txfifoempty(dev) dev->ops->txfifoempty(dev)
+#define uart_send(dev,ch) dev->ops->send(dev,ch)
+#define uart_receive(dev,s) dev->ops->receive(dev,s)
+
+/************************************************************************************
+ * Private Types
+ ************************************************************************************/
+
+/* This structure defines one serial I/O buffer. The serial infrastructure will
+ * initialize the 'sem' field but all other fields must be initialized by the
+ * caller of uart_register().
+ */
+
+struct uart_buffer_s
+{
+ sem_t sem; /* Used to control exclusive access to the buffer */
+ sint16 head; /* Index to the head [IN] index in the buffer */
+ sint16 tail; /* Index to the tail [OUT] index in the buffer */
+ sint16 size; /* The allocated size of the buffer */
+ FAR char *buffer; /* Pointer to the allocated buffer memory */
+};
+
+/* This structure defines all of the operations providd by the architecture specific
+ * logic. All fields must be provided with non-NULL function pointers by the
+ * caller of uart_register().
+ */
+
+struct uart_dev_s;
+struct uart_ops_s
+{
+ /* Configure the UART baud, bits, parity, fifos, etc. This method is called
+ * the first time that the serial port is opened.
+ */
+
+ int (*setup)(struct uart_dev_s *dev);
+
+ /* Disable the UART. This method is called when the serial port is closed */
+
+ void (*shutdown)(struct uart_dev_s *dev);
+
+ /* This is the UART interrupt handler. It will be invoked when an interrupt
+ * received on the 'irq' It should call uart_transmitchars or uart_receivechar
+ * to perform the appropriate data transfers. The interrupt handling logic\
+ * must be able to map the 'irq' number into the approprite uart_dev_s
+ * structure in order to call these functions.
+ */
+
+ int (*handler)(int irq, void *context);
+
+ /* All ioctl calls will be routed through this method */
+
+ int (*ioctl)(struct file *filep, int cmd, unsigned long arg);
+
+ /* Called (usually) from the interrupt level to receive one character from
+ * the UART. Error bits associated with the receipt are provided in the
+ * the return 'status'.
+ */
+
+ int (*receive)(struct uart_dev_s *dev, unsigned int *status);
+
+ /* Call to enable or disable RX interrupts */
+
+ void (*rxint)(struct uart_dev_s *dev, boolean enable);
+
+ /* Return TRUE if the receive fifo is not empty */
+
+ boolean (*rxfifonotempty)(struct uart_dev_s *dev);
+
+ /* This method will send one byte on the UART */
+
+ void (*send)(struct uart_dev_s *dev, int ch);
+
+ /* Call to enable or disable TX interrupts */
+
+ void (*txint)(struct uart_dev_s *dev, boolean enable);
+
+ /* Return TRUE if the tranmsit fifo is not full. This is used to
+ * determine if *send can be called.
+ */
+
+ boolean (*txfifonotfull)(struct uart_dev_s *dev);
+
+ /* Return TRUE if the transmit fifo is empty. This is used when the
+ * driver needs to make sure that all characters are "drained" from
+ * the TX fifo.
+ */
+
+ boolean (*txfifoempty)(struct uart_dev_s *dev);
+};
+
+/* This is the device structure used by the driver. The caller of
+ * uart_register() must allocate and initialize this structure. The
+ * calling logic need only set all fields to zero except:
+ *
+ * 'irq', 'isconsole', 'xmit.buffer', 'rcv.buffer', the elements
+ * of 'ops', and 'private'
+ *
+ * The common logic will initialize all semaphores.
+ */
+
+struct uart_dev_s
+{
+ int open_count; /* The number of times
+ * the device has been opened */
+ ubyte irq; /* IRQ associated with
+ * this UART */
+ boolean xmitwaiting; /* TRUE: User is waiting
+ * for space in xmit.buffer */
+ boolean recvwaiting; /* TRUE: User is waiting
+ * for space in recv.buffer */
+ boolean isconsole; /* TRUE: This is the serial console */
+ sem_t closesem; /* Locks out new opens while
+ * close is in progress */
+ sem_t xmitsem; /* Used to wakeup user waiting
+ * for space in xmit.buffer */
+ sem_t recvsem; /* Used to wakeup user waiting
+ * for sapce in recv.buffer */
+ struct uart_buffer_s xmit; /* Describes transmit buffer */
+ struct uart_buffer_s recv; /* Describes receive buffer */
+ const struct uart_ops_s *ops; /* Arch-specifics operations */
+ void *priv; /* Used by the arch-specific logic */
+};
+typedef struct uart_dev_s uart_dev_t;
+
+/************************************************************************************
+ * Public Data
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/************************************************************************************
+ * Name: uart_register
+ *
+ * Description:
+ * Register serial console and serial ports.
+ *
+ ************************************************************************************/
+
+EXTERN int uart_register(const char *path, uart_dev_t *dev);
+
+/************************************************************************************
+ * Name: uart_xmitchars
+ *
+ * Description:
+ * This function is called from the UART interrupt handler when an interrupt
+ * is received indicating that there is more space in the transmit FIFO. This
+ * function will send characters from the tail of the xmit buffer while the driver
+ * write() logic adds data to the head of the xmit buffer.
+ *
+ ************************************************************************************/
+
+EXTERN void uart_xmitchars(uart_dev_t *dev);
+
+/************************************************************************************
+ * Name: uart_receivechars
+ *
+ * Description:
+ * This function is called from the UART interrupt handler when an interrupt
+ * is received indicating that are bytes available in the receive fifo. This
+ * function will add chars to head of receive buffer. Driver read() logic will take
+ * characters from the tail of the buffer.
+ *
+ ************************************************************************************/
+
+EXTERN void uart_recvchars(uart_dev_t *dev);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __SERIAL_H */