diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2008-11-17 23:22:27 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2008-11-17 23:22:27 +0000 |
commit | 09f70284f5e1d190519661166422909e69b2331b (patch) | |
tree | b968095164f6f6417386d02feda27ea7e7d434ca | |
parent | 5c3162da749c8c8c1609c1ab1c85ab1961dbabde (diff) | |
download | px4-nuttx-09f70284f5e1d190519661166422909e69b2331b.tar.gz px4-nuttx-09f70284f5e1d190519661166422909e69b2331b.tar.bz2 px4-nuttx-09f70284f5e1d190519661166422909e69b2331b.zip |
Add poll method to serial drivers
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1268 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r-- | nuttx/ChangeLog | 2 | ||||
-rw-r--r-- | nuttx/Documentation/NuttX.html | 2 | ||||
-rw-r--r-- | nuttx/arch/sim/src/up_devconsole.c | 14 | ||||
-rw-r--r-- | nuttx/drivers/serial.c | 184 | ||||
-rw-r--r-- | nuttx/drivers/serialirq.c | 41 | ||||
-rw-r--r-- | nuttx/drivers/usbdev/usbdev_serial.c | 59 | ||||
-rw-r--r-- | nuttx/examples/poll/poll_listener.c | 159 | ||||
-rw-r--r-- | nuttx/include/nuttx/serial.h | 48 |
8 files changed, 401 insertions, 108 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index 32760238a..f6e64259c 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -565,6 +565,6 @@ 0.3.19 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr> * Add poll() and select() APIs (in the initial check-in, these work only with character devices) - * Add poll() methods to /dev/null, /dev/zero, pipes, and fifos. + * Add poll() methods to /dev/null, /dev/zero, pipes, fifos, and serial drivers. * Add examples/poll for testing poll() and select() diff --git a/nuttx/Documentation/NuttX.html b/nuttx/Documentation/NuttX.html index e149f42a8..cf3e9603d 100644 --- a/nuttx/Documentation/NuttX.html +++ b/nuttx/Documentation/NuttX.html @@ -1201,7 +1201,7 @@ buildroot-0.1.2 2007-11-06 <spudmonkey@racsa.co.cr> <pre><ul> nuttx-0.3.19 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr> * Add poll() and select() APIs (in the initial check-in, these work only with character devices) - * Add poll() methods to /dev/null, /dev/zero, pipes, and fifos. + * Add poll() methods to /dev/null, /dev/zero, pipes, fifos, and serial drivers. * Add examples/poll for testing poll() and select() pascal-0.1.3 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr> diff --git a/nuttx/arch/sim/src/up_devconsole.c b/nuttx/arch/sim/src/up_devconsole.c index 6bf733f71..58fa21e3b 100644 --- a/nuttx/arch/sim/src/up_devconsole.c +++ b/nuttx/arch/sim/src/up_devconsole.c @@ -53,6 +53,9 @@ static ssize_t devconsole_read(struct file *, char *, size_t); static ssize_t devconsole_write(struct file *, const char *, size_t); +#ifndef CONFIG_DISABLE_POLL +static int devconsole_poll(FAR struct file *filep, FAR struct pollfd *fds); +#endif /**************************************************************************** * Private Data @@ -62,14 +65,16 @@ static struct file_operations devconsole_fops = { .read = devconsole_read, .write = devconsole_write, +#ifndef CONFIG_DISABLE_POLL + .poll = devconsole_poll, +#endif }; /**************************************************************************** * Private Functions ****************************************************************************/ - - static ssize_t devconsole_read(struct file *filp, char *buffer, size_t len) +static ssize_t devconsole_read(struct file *filp, char *buffer, size_t len) { return up_hostread(buffer, len); } @@ -79,6 +84,11 @@ static ssize_t devconsole_write(struct file *filp, const char *buffer, size_t le return up_hostwrite(buffer, len); } +static int devconsole_poll(FAR struct file *filep, FAR struct pollfd *fds) +{ + return OK; +} + /**************************************************************************** * Public Functions ****************************************************************************/ diff --git a/nuttx/drivers/serial.c b/nuttx/drivers/serial.c index 366c7a208..2939bf61f 100644 --- a/nuttx/drivers/serial.c +++ b/nuttx/drivers/serial.c @@ -44,6 +44,7 @@ #include <semaphore.h> #include <string.h> #include <fcntl.h> +#include <poll.h> #include <errno.h> #include <debug.h> @@ -77,6 +78,9 @@ static int uart_close(FAR struct file *filep); static ssize_t uart_read(FAR struct file *filep, FAR char *buffer, size_t buflen); static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer, size_t buflen); static int uart_ioctl(FAR struct file *filep, int cmd, unsigned long arg); +#ifndef CONFIG_DISABLE_POLL +static int uart_poll(FAR struct file *filep, FAR struct pollfd *fds); +#endif /************************************************************************************ * Private Variables @@ -89,8 +93,10 @@ struct file_operations g_serialops = uart_read, /* read */ uart_write, /* write */ 0, /* seek */ - uart_ioctl, /* ioctl */ - 0 /* poll */ + uart_ioctl /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , uart_poll /* poll */ +#endif }; /************************************************************************************ @@ -119,6 +125,33 @@ static void uart_takesem(FAR sem_t *sem) #define uart_givesem(sem) (void)sem_post(sem) +/**************************************************************************** + * Name: uart_pollnotify + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +static void uart_pollnotify(FAR uart_dev_t *dev, pollevent_t eventset) +{ + int i; + + for (i = 0; i < CONFIG_DEV_CONSOLE_NPOLLWAITERS; i++) + { + struct pollfd *fds = dev->fds[i]; + if (fds) + { + fds->revents |= (fds->events & eventset); + if (fds->revents != 0) + { + fvdbg("Report events: %02x\n", fds->revents); + sem_post(fds->sem); + } + } + } +} +#else +# define uart_pollnotify(dev,event) +#endif + /************************************************************************************ * Name: uart_putxmitchar ************************************************************************************/ @@ -340,6 +373,98 @@ static int uart_ioctl(FAR struct file *filep, int cmd, unsigned long arg) return dev->ops->ioctl(filep, cmd, arg); } +/**************************************************************************** + * Name: uart_poll + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +int uart_poll(FAR struct file *filep, FAR struct pollfd *fds) +{ + FAR struct inode *inode = filep->f_inode; + FAR uart_dev_t *dev = inode->i_private; + pollevent_t eventset; + int ndx; + int i; + + /* Some sanity checking */ +#if CONFIG_DEBUG + if (!dev) + { + return -ENODEV; + } +#endif + + /* Find an available slot for the poll structure reference */ + + uart_takesem(&dev->pollsem); + for (i = 0; i < CONFIG_DEV_CONSOLE_NPOLLWAITERS; i++) + { + /* Find the slot with the value equal to filep->f_priv. If there + * is not previously installed poll structure, then f_priv will + * be NULL and we will find the first unused slot. If f_priv is + * is non-NULL, then we will find the slot that was used for the + * previous setup. + */ + + if (dev->fds[i] == filep->f_priv) + { + dev->fds[i] = fds; + break; + } + } + + if (i >= CONFIG_DEV_CONSOLE_NPOLLWAITERS) + { + DEBUGASSERT(fds == NULL); + return -EBUSY; + } + + /* Set or clear the poll event structure reference in the 'struct file' + * private data. + */ + + filep->f_priv = fds; + + /* Check if we should immediately notify on any of the requested events */ + + if (fds) + { + /* Check if the xmit buffer is full. */ + + eventset = 0; + + uart_takesem(&dev->xmit.sem); + ndx = dev->xmit.head + 1; + if (ndx >= dev->xmit.size) + { + ndx = 0; + } + if (ndx != dev->xmit.tail) + { + eventset |= POLLOUT; + } + uart_givesem(&dev->xmit.sem); + + /* Check if the receive buffer is empty */ + + uart_takesem(&dev->recv.sem); + if (dev->recv.head != dev->recv.tail) + { + eventset |= POLLIN; + } + uart_givesem(&dev->recv.sem); + + if (eventset) + { + uart_pollnotify(dev, eventset); + } + } + + uart_givesem(&dev->pollsem); + return OK; +} +#endif + /************************************************************************************ * Name: uart_close * @@ -513,7 +638,62 @@ int uart_register(FAR const char *path, FAR uart_dev_t *dev) sem_init(&dev->closesem, 0, 1); sem_init(&dev->xmitsem, 0, 0); sem_init(&dev->recvsem, 0, 0); +#ifndef CONFIG_DISABLE_POLL + sem_init(&dev->pollsem, 0, 1); +#endif dbg("Registering %s\n", path); return register_driver(path, &g_serialops, 0666, dev); } + +/************************************************************************************ + * Name: uart_datareceived + * + * Description: + * This function is called from uart_recvchars when new serial data is place in + * the driver's circular buffer. This function will wake-up any stalled read() + * operations that are waiting for incoming data. + * + ************************************************************************************/ + +void uart_datareceived(FAR uart_dev_t *dev) +{ + /* Awaken any awaiting read() operations */ + + if (dev->recvwaiting) + { + dev->recvwaiting = FALSE; + (void)sem_post(&dev->recvsem); + } + + /* Notify all poll/select waiters that they can read from the recv buffer */ + + uart_pollnotify(dev, POLLIN); + +} + +/************************************************************************************ + * Name: uart_datasent + * + * Description: + * This function is called from uart_xmitchars after serial data has been sent, + * freeing up some space in the driver's circular buffer. This function will + * wake-up any stalled write() operations that was waiting for space to buffer + * outgoing data. + * + ************************************************************************************/ + +void uart_datasent(FAR uart_dev_t *dev) +{ + if (dev->xmitwaiting) + { + dev->xmitwaiting = FALSE; + (void)sem_post(&dev->xmitsem); + } + + /* Notify all poll/select waiters that they can write to xmit buffer */ + + uart_pollnotify(dev, POLLOUT); +} + + diff --git a/nuttx/drivers/serialirq.c b/nuttx/drivers/serialirq.c index f7503e4cc..d1a18b257 100644 --- a/nuttx/drivers/serialirq.c +++ b/nuttx/drivers/serialirq.c @@ -80,6 +80,8 @@ void uart_xmitchars(FAR uart_dev_t *dev) { + uint16 nbytes = 0; + /* Send while we still have data & room in the fifo */ while (dev->xmit.head != dev->xmit.tail && uart_txready(dev)) @@ -87,6 +89,7 @@ void uart_xmitchars(FAR uart_dev_t *dev) /* Send the next byte */ uart_send(dev, dev->xmit.buffer[dev->xmit.tail]); + nbytes++; /* Increment the tail index */ @@ -94,16 +97,6 @@ void uart_xmitchars(FAR uart_dev_t *dev) { dev->xmit.tail = 0; } - - /* A byte was removed from the buffer. Inform any waiters - * there there is space available. - */ - - if (dev->xmitwaiting) - { - dev->xmitwaiting = FALSE; - (void)sem_post(&dev->xmitsem); - } } /* When all of the characters have been sent from the buffer @@ -114,6 +107,15 @@ void uart_xmitchars(FAR uart_dev_t *dev) { uart_disabletxint(dev); } + + /* If any bytes were removed from the buffer, inform any waiters + * there there is space available. + */ + + if (nbytes) + { + uart_datasent(dev); + } } /************************************************************************************ @@ -131,6 +133,7 @@ void uart_recvchars(FAR uart_dev_t *dev) { unsigned int status; int nexthead = dev->recv.head + 1; + uint16 nbytes = 0; if (nexthead >= dev->recv.size) { @@ -146,6 +149,7 @@ void uart_recvchars(FAR uart_dev_t *dev) /* Add the character to the buffer */ dev->recv.buffer[dev->recv.head] = uart_receive(dev, &status); + nbytes++; /* Increment the head index */ @@ -154,18 +158,15 @@ void uart_recvchars(FAR uart_dev_t *dev) { nexthead = 0; } + } - /* A character was added... if there is a thread waiting for more data, then - * post the recvsem semaphore to wake it up. NOTE: There is a logic error in - * the above looping logic: If nexthead == dev->recv.tail on entry and - * recvwaiting is true, the recvsem will never get posted! - */ + /* If any bytes were added to the buffer, inform any waiters + * there there is new incoming data available. + */ - if (dev->recvwaiting) - { - dev->recvwaiting = FALSE; - (void)sem_post(&dev->recvsem); - } + if (nbytes) + { + uart_datareceived(dev); } } diff --git a/nuttx/drivers/usbdev/usbdev_serial.c b/nuttx/drivers/usbdev/usbdev_serial.c index 4b32ac052..116accc57 100644 --- a/nuttx/drivers/usbdev/usbdev_serial.c +++ b/nuttx/drivers/usbdev/usbdev_serial.c @@ -526,14 +526,6 @@ static uint16 usbclass_fillrequest(FAR struct usbser_dev_s *priv, char *reqbuf, { xmit->tail = 0; } - - /* Check if we have to wake up the serial driver */ - - if (serdev->xmitwaiting) - { - serdev->xmitwaiting = FALSE; - sem_post(&serdev->xmitsem); - } } /* When all of the characters have been sent from the buffer @@ -545,6 +537,15 @@ static uint16 usbclass_fillrequest(FAR struct usbser_dev_s *priv, char *reqbuf, uart_disabletxint(serdev); } + /* If any bytes were removed from the buffer, inform any waiters + * there there is space available. + */ + + if (nbytes) + { + uart_datasent(serdev); + } + irqrestore(flags); return nbytes; } @@ -651,6 +652,7 @@ static inline int usbclass_recvpacket(FAR struct usbser_dev_s *priv, FAR struct uart_buffer_s *recv = &serdev->recv; uint16 currhead; uint16 nexthead; + uint16 nbytes = 0; /* Get the next head index. During the time that RX interrupts are disabled, the * the serial driver will be extracting data from the circular buffer and modifying @@ -684,7 +686,7 @@ static inline int usbclass_recvpacket(FAR struct usbser_dev_s *priv, * then we have overrun the serial driver and data will be lost. */ - while (nexthead != recv->tail && reqlen > 0) + while (nexthead != recv->tail && nbytes < reqlen) { /* Copy one byte to the head of the circular RX buffer */ @@ -693,21 +695,7 @@ static inline int usbclass_recvpacket(FAR struct usbser_dev_s *priv, /* Update counts and indices */ currhead = nexthead; - reqlen--; - - /* Wake up the serial driver if it is waiting for incoming data. If we - * are running in an interrupt handler, then the serial driver will - * not run until the interrupt handler returns. But we will exercise - * care in the following just in case the serial driver does run. - */ - - if (priv->rxenabled && serdev->recvwaiting) - { - recv->head = currhead; - serdev->recvwaiting = FALSE; - sem_post(&serdev->recvsem); - currhead = recv->head; - } + nbytes++; /* Increment the head index and check for wrap around */ @@ -731,9 +719,20 @@ static inline int usbclass_recvpacket(FAR struct usbser_dev_s *priv, priv->rxhead = currhead; } + /* If data was added to the incoming serial buffer, then wake up any + * threads is waiting for incoming data. If we are running in an interrupt + * handler, then the serial driver will not run until the interrupt handler + * returns. + */ + + if (priv->rxenabled && nbytes > 0) + { + uart_datareceived(serdev); + } + /* Return an error if the entire packet could not be transferred */ - if (reqlen > 0) + if (nbytes < reqlen) { usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RXOVERRUN), 0); return -ENOSPC; @@ -2017,15 +2016,9 @@ static void usbser_rxint(FAR struct uart_dev_s *dev, boolean enable) { serdev->recv.head = priv->rxhead; - /* Is the serial driver waiting for more data? */ + /* Yes... signal the availability of new data */ - if (serdev->recvwaiting) - { - /* Yes... signal the availability of new data */ - - sem_post(&serdev->recvsem); - serdev->recvwaiting = FALSE; - } + uart_datareceived(serdev); } /* RX "interrupts are no longer disabled */ diff --git a/nuttx/examples/poll/poll_listener.c b/nuttx/examples/poll/poll_listener.c index 6182ca0de..c798b6e88 100644 --- a/nuttx/examples/poll/poll_listener.c +++ b/nuttx/examples/poll/poll_listener.c @@ -57,6 +57,17 @@ * Definitions ****************************************************************************/ +#if defined(CONFIG_DEV_CONSOLE) && !defined(CONFIG_DEV_LOWCONSOLE) +# define HAVE_CONSOLE +# define NPOLLFDS 2 +# define CONSNDX 0 +# define FIFONDX 1 +#else +# undef HAVE_CONSOLE +# define NPOLLFDS 1 +# define FIFONDX 0 +#endif + /**************************************************************************** * Private Types ****************************************************************************/ @@ -79,13 +90,15 @@ void *poll_listener(pthread_addr_t pvarg) { - struct pollfd fds; + struct pollfd fds[NPOLLFDS]; char buffer[64]; ssize_t nbytes; boolean timeout; boolean pollin; + int nevents; int fd; int ret; + int i; /* Open the FIFO for non-blocking read */ @@ -105,15 +118,20 @@ void *poll_listener(pthread_addr_t pvarg) { message("poll_listener: Calling poll()\n"); - memset(&fds, 0, sizeof(struct pollfd)); - fds.fd = fd; - fds.events = POLLIN; - fds.revents = 0; + memset(fds, 0, sizeof(struct pollfd)*NPOLLFDS); +#ifdef HAVE_CONSOLE + fds[CONSNDX].fd = 0; + fds[CONSNDX].events = POLLIN; + fds[CONSNDX].revents = 0; +#endif + fds[FIFONDX].fd = fd; + fds[FIFONDX].events = POLLIN; + fds[FIFONDX].revents = 0; - timeout = FALSE; - pollin = FALSE; + timeout = FALSE; + pollin = FALSE; - ret = poll(&fds, 1, POLL_LISTENER_DELAY); + ret = poll(fds, NPOLLFDS, POLL_LISTENER_DELAY); message("\npoll_listener: poll returned: %d\n", ret); if (ret < 0) @@ -122,71 +140,116 @@ void *poll_listener(pthread_addr_t pvarg) } else if (ret == 0) { - message("poll_listener: Timeout, revents=%02x\n", fds.revents); + message("poll_listener: Timeout\n"); timeout = TRUE; - if (fds.revents != 0) - { - message("poll_listener: ERROR? expected revents=00, received revents=%02x\n", - fds.revents); - } + } + else if (ret > NPOLLFDS) + { + message("poll_listener: ERROR poll reported: %d\n"); } else { - if (ret != 1) + pollin = TRUE; + } + + nevents = 0; + for (i = 0; i < NPOLLFDS; i++) + { + message("poll_listener: FIFO revents[%d]=%02x\n", i, fds[i].revents); + if (timeout) { - message("poll_listener: ERROR poll reported: %d\n"); + if (fds[i].revents != 0) + { + message("poll_listener: ERROR? expected revents=00, received revents[%d]=%02x\n", + fds[i].revents, i); + } } - else + else if (pollin) { - pollin = TRUE; + if (fds[i].revents == POLLIN) + { + nevents++; + } + else if (fds[i].revents != 0) + { + message("poll_listener: ERROR unexpected revents[i]=%02x\n", + i, fds[i].revents); + } } + } - message("poll_listener: revents=%02x\n", fds.revents); - if (fds.revents != POLLIN) - { - message("poll_listener: ERROR expected revents=%02x, received revents=%02x\n", - fds.revents); - message(" (might just be a race condition)\n"); - } + if (pollin && nevents != ret) + { + message("poll_listener: ERROR found %d events, poll reported %d\n", nevents, ret); } - /* In any event, read until the pipe is empty */ + /* In any event, read until the pipe/serial is empty */ - do + for (i = 0; i < NPOLLFDS; i++) { - nbytes = read(fd, buffer, 63); - if (nbytes <= 0) + do { - if (nbytes == 0 || errno == EAGAIN) +#ifdef HAVE_CONSOLE + /* Hack to work around the fact that the console driver on the + * simulator is always non-blocking. + */ + + if (i == CONSNDX) { - if (pollin) + if ((fds[CONSNDX].revents & POLLIN) != 0) + { + buffer[0] = getchar(); + nbytes = 1; + } + else { - message("poll_listener: ERROR no read data\n"); + nbytes = 0; } } - else if (errno != EINTR) + else +#endif { - message("poll_listener: read failed: %d\n", errno); + /* The pipe works differently, it returns whatever data + * it has available without blocking. + */ + + nbytes = read(fds[i].fd, buffer, 63); } - nbytes = 0; - } - else - { - if (timeout) + + if (nbytes <= 0) { - message("poll_listener: ERROR? Poll timeout, but data read\n"); - message(" (might just be a race condition)\n"); + if (nbytes == 0 || errno == EAGAIN) + { + if ((fds[i].revents & POLLIN) != 0) + { + message("poll_listener: ERROR no read data[%d]\n", i); + } + } + else if (errno != EINTR) + { + message("poll_listener: read[%d] failed: %d\n", i, errno); + } + nbytes = 0; } + else + { + if (timeout) + { + message("poll_listener: ERROR? Poll timeout, but data read[%d]\n", i); + message(" (might just be a race condition)\n"); + } - buffer[nbytes] = '\0'; - message("poll_listener: Read '%s' (%d bytes)\n", buffer, nbytes); - } + buffer[nbytes] = '\0'; + message("poll_listener: Read[%d] '%s' (%d bytes)\n", i, buffer, nbytes); + } - timeout = FALSE; - pollin = FALSE; - } - while (nbytes > 0); + /* Suppress error report if no read data on the next time through */ + fds[i].revents = 0; + } + while (nbytes > 0); + } + /* Make sure that everything is displayed */ msgflush(); diff --git a/nuttx/include/nuttx/serial.h b/nuttx/include/nuttx/serial.h index 9954c16c0..ed5c6a1c0 100644 --- a/nuttx/include/nuttx/serial.h +++ b/nuttx/include/nuttx/serial.h @@ -49,6 +49,14 @@ * Definitions ************************************************************************************/ +/* Maximum number of threads than can be waiting for POLL events */ + +#ifndef CONFIG_DEV_CONSOLE_NPOLLWAITERS +# define CONFIG_DEV_CONSOLE_NPOLLWAITERS 2 +#endif + +/* vtable access helpers */ + #define uart_setup(dev) dev->ops->setup(dev) #define uart_shutdown(dev) dev->ops->shutdown(dev) #define uart_attach(dev) dev->ops->attach(dev) @@ -186,10 +194,23 @@ struct uart_dev_s sem_t closesem; /* Locks out new open while close is in progress */ sem_t xmitsem; /* Wakeup user waiting for space in xmit.buffer */ sem_t recvsem; /* Wakeup user waiting for data in recv.buffer */ +#ifndef CONFIG_DISABLE_POLL + sem_t pollsem; /* Manages exclusive access to fds[] */ +#endif struct uart_buffer_s xmit; /* Describes transmit buffer */ struct uart_buffer_s recv; /* Describes receive buffer */ FAR const struct uart_ops_s *ops; /* Arch-specific operations */ - FAR void *priv; /* Used by the arch-specific logic */ + FAR void *priv; /* Used by the arch-specific logic */ + + /* The following is a list if poll structures of threads waiting for + * driver events. The 'struct pollfd' reference for each open is also + * retained in the f_priv field of the 'struct file'. + */ + +#ifndef CONFIG_DISABLE_POLL + struct pollfd *fds[CONFIG_DEV_CONSOLE_NPOLLWAITERS]; +#endif + }; typedef struct uart_dev_s uart_dev_t; @@ -245,6 +266,31 @@ EXTERN void uart_xmitchars(FAR uart_dev_t *dev); EXTERN void uart_recvchars(FAR uart_dev_t *dev); +/************************************************************************************ + * Name: uart_datareceived + * + * Description: + * This function is called from uart_recvchars when new serial data is place in + * the driver's circular buffer. This function will wake-up any stalled read() + * operations that are waiting for incoming data. + * + ************************************************************************************/ + +EXTERN void uart_datareceived(FAR uart_dev_t *dev); + +/************************************************************************************ + * Name: uart_datasent + * + * Description: + * This function is called from uart_xmitchars after serial data has been sent, + * freeing up some space in the driver's circular buffer. This function will + * wake-up any stalled write() operations that was waiting for space to buffer + * outgoing data. + * + ************************************************************************************/ + +EXTERN void uart_datasent(FAR uart_dev_t *dev); + #undef EXTERN #if defined(__cplusplus) } |