summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-03-13 15:12:31 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-03-13 15:12:31 +0000
commit08a603c77b99ade6a63938a62e1cd785e9fabd25 (patch)
treee73122d7e6073b1386302e2b5a477c72eb80c171
parentd4f43430da40993103b774b5f07a9da3ef3aedf0 (diff)
downloadnuttx-08a603c77b99ade6a63938a62e1cd785e9fabd25.tar.gz
nuttx-08a603c77b99ade6a63938a62e1cd785e9fabd25.tar.bz2
nuttx-08a603c77b99ade6a63938a62e1cd785e9fabd25.zip
SLIP corrections
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3376 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--nuttx/ChangeLog7
-rw-r--r--nuttx/Documentation/NuttX.html10
-rwxr-xr-xnuttx/configs/olimex-lpc1766stk/slip-httpd/defconfig4
-rw-r--r--nuttx/drivers/net/slip.c186
-rw-r--r--nuttx/include/net/uip/uip-arch.h36
-rw-r--r--nuttx/lib/lib_fopen.c35
6 files changed, 154 insertions, 124 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 3359e5e8f..12aff230a 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -1555,3 +1555,10 @@
5.20 2011-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
+ * lib/lib_fopen() -- fopen() was not returning the correct errno value
+ when the underlying open() failed.
+ * include/net/uip/uip-arch.h -- The uIP interface has been extended
+ slightly so that drivers can be concurrenly filling and sending
+ packet buffers. This capability was needed by the SLIP driver.
+ * drivers/net/slip.c -- Several corrections and some re-design of
+ of the driver. \ No newline at end of file
diff --git a/nuttx/Documentation/NuttX.html b/nuttx/Documentation/NuttX.html
index d7187464f..4af5e5c9d 100644
--- a/nuttx/Documentation/NuttX.html
+++ b/nuttx/Documentation/NuttX.html
@@ -8,7 +8,7 @@
<tr align="center" bgcolor="#e4e4e4">
<td>
<h1><big><font color="#3c34ec"><i>NuttX RTOS</i></font></big></h1>
- <p>Last Updated: March 12, 2011</p>
+ <p>Last Updated: March 13, 2011</p>
</td>
</tr>
</table>
@@ -2177,6 +2177,14 @@ buildroot-1.9 2011-02-10 &lt;spudmonkey@racsa.co.cr&gt;
<ul><pre>
nuttx-5.20 2011-xx-xx Gregory Nutt &lt;spudmonkey@racsa.co.cr&gt;
+ * lib/lib_fopen() -- fopen() was not returning the correct errno value
+ when the underlying open() failed.
+ * include/net/uip/uip-arch.h -- The uIP interface has been extended
+ slightly so that drivers can be concurrenly filling and sending
+ packet buffers. This capability was needed by the SLIP driver.
+ * drivers/net/slip.c -- Several corrections and some re-design of
+ of the driver.
+
pascal-2.1 2011-xx-xx Gregory Nutt &lt;spudmonkey@racsa.co.cr&gt;
buildroot-1.10 2011-xx-xx &lt;spudmonkey@racsa.co.cr&gt;
diff --git a/nuttx/configs/olimex-lpc1766stk/slip-httpd/defconfig b/nuttx/configs/olimex-lpc1766stk/slip-httpd/defconfig
index 105481034..f61039535 100755
--- a/nuttx/configs/olimex-lpc1766stk/slip-httpd/defconfig
+++ b/nuttx/configs/olimex-lpc1766stk/slip-httpd/defconfig
@@ -336,7 +336,7 @@ CONFIG_START_DAY=23
CONFIG_GREGORIAN_TIME=n
CONFIG_JULIAN_TIME=n
CONFIG_DEV_CONSOLE=y
-CONFIG_DEV_LOWCONSOLE=y
+CONFIG_DEV_LOWCONSOLE=n
CONFIG_MUTEX_TYPES=n
CONFIG_PRIORITY_INHERITANCE=n
CONFIG_SEM_PREALLOCHOLDERS=0
@@ -520,6 +520,7 @@ CONFIG_MMCSD_HAVECARDDETECT=n
# TCP/IP and UDP support via uIP
# CONFIG_NET - Enable or disable all network features
# CONFIG_NET_SLIP - Use the SLIP data link layer (L2)
+# CONFIG_NET_MULTIBUFFER - Use multiple input/output buffers (probably no)
# CONFIG_NET_IPv6 - Build in support for IPv6
# CONFIG_NSOCKET_DESCRIPTORS - Maximum number of socket descriptors per task/thread.
# CONFIG_NET_SOCKOPTS - Enable or disable support for socket options
@@ -545,6 +546,7 @@ CONFIG_MMCSD_HAVECARDDETECT=n
#
CONFIG_NET=y
CONFIG_NET_SLIP=y
+CONFIG_NET_MULTIBUFFER=y
CONFIG_NET_IPv6=n
CONFIG_NSOCKET_DESCRIPTORS=16
CONFIG_NET_SOCKOPTS=y
diff --git a/nuttx/drivers/net/slip.c b/nuttx/drivers/net/slip.c
index 9f73ae76e..c3dcb5e03 100644
--- a/nuttx/drivers/net/slip.c
+++ b/nuttx/drivers/net/slip.c
@@ -52,7 +52,6 @@
#include <fcntl.h>
#include <unistd.h>
#include <wdog.h>
-#include <poll.h>
#include <errno.h>
#include <debug.h>
@@ -138,9 +137,10 @@ struct slip_driver_s
{
bool bifup; /* true:ifup false:ifdown */
WDOG_ID txpoll; /* TX poll timer */
- int fd; /* File descriptor associated with stream */
FILE *stream; /* The contained serial stream */
+ pid_t pid; /* Receiver thread ID */
sem_t waitsem; /* Only used at start-up */
+ uint16_t rxlen; /* The number of bytes in rxbuf */
/* Driver statistics */
@@ -151,6 +151,8 @@ struct slip_driver_s
/* This holds the information visible to uIP/NuttX */
struct uip_driver_s dev; /* Interface understood by uIP */
+ uint8_t rxbuf[CONFIG_NET_BUFSIZE + 2];
+ uint8_t txbuf[CONFIG_NET_BUFSIZE + 2];
};
/****************************************************************************
@@ -180,7 +182,6 @@ static int slip_uiptxpoll(struct uip_driver_s *dev);
/* Packet receiver task */
static inline int slip_getc(FAR struct slip_driver_s *priv);
-static inline void slip_readpacket(FAR struct slip_driver_s *priv);
static inline void slip_receive(FAR struct slip_driver_s *priv);
static int slip_rxtask(int argc, char *argv[]);
@@ -375,6 +376,7 @@ static int slip_transmit(FAR struct slip_driver_s *priv)
{
slip_write(priv, start, len);
}
+ fflush(priv->stream);
/* And send the END token */
@@ -448,7 +450,7 @@ static inline int slip_getc(FAR struct slip_driver_s *priv)
}
/****************************************************************************
- * Function: slip_readpacket
+ * Function: slip_receive
*
* Description:
* Read a packet from the serial input
@@ -461,12 +463,11 @@ static inline int slip_getc(FAR struct slip_driver_s *priv)
*
****************************************************************************/
-static inline void slip_readpacket(FAR struct slip_driver_s *priv)
+static inline void slip_receive(FAR struct slip_driver_s *priv)
{
uint8_t ch;
- int nbytes = 0;
- /* Copy the data data from the hardware to priv->dev.d_buf until we
+ /* Copy the data data from the hardware to to the RX buffer until we
* put together a whole packet. Make sure not to copy them into the
* packet if we run out of room.
*/
@@ -474,7 +475,7 @@ static inline void slip_readpacket(FAR struct slip_driver_s *priv)
nvdbg("Receiving packet\n");
for (;;)
{
- /* Get the next character in the stream */
+ /* Get the next character in the stream. */
ch = slip_getc(priv);
@@ -489,16 +490,15 @@ static inline void slip_readpacket(FAR struct slip_driver_s *priv)
case SLIP_END:
nvdbg("END\n");
- /* a minor optimization: if there is no data in the packet, ignore
+ /* A minor optimization: if there is no data in the packet, ignore
* it. This is meant to avoid bothering IP with all the empty
* packets generated by the duplicate END characters which are in
* turn sent to try to detect line noise.
*/
- if (nbytes > 0)
+ if (priv->rxlen > 0)
{
- nvdbg("Received packet size %d\n", nbytes);
- priv->dev.d_len = nbytes;
+ nvdbg("Received packet size %d\n", priv->rxlen);
return;
}
break;
@@ -523,8 +523,8 @@ static inline void slip_readpacket(FAR struct slip_driver_s *priv)
nvdbg("ESC-END\n");
ch = SLIP_END;
break;
- nvdbg("ESC-ESC\n");
case SLIP_ESC_ESC:
+ nvdbg("ESC-ESC\n");
ch = SLIP_ESC;
break;
default:
@@ -537,9 +537,9 @@ static inline void slip_readpacket(FAR struct slip_driver_s *priv)
*/
default:
- if (nbytes < priv->dev.d_len)
+ if (priv->rxlen < CONFIG_NET_BUFSIZE+2)
{
- priv->dev.d_buf[nbytes++] = ch;
+ priv->rxbuf[priv->rxlen++] = ch;
}
break;
}
@@ -547,48 +547,6 @@ static inline void slip_readpacket(FAR struct slip_driver_s *priv)
}
/****************************************************************************
- * Function: slip_receive
- *
- * Description:
- * Accept and handle an incoming packet.
- *
- * Parameters:
- * priv - Reference to the driver state structure
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- * Global interrupts are disabled by interrupt handling logic.
- *
- ****************************************************************************/
-
-static inline void slip_receive(FAR struct slip_driver_s *priv)
-{
- /* Copy the data data from the hardware to priv->dev.d_buf until we put
- * together a whole packet.
- */
-
- slip_readpacket(priv);
- SLIP_STAT(priv, received);
-
- /* All packets are assumed to be IP packets (we don't have a choice.. there
- * is no Ethernet header containing the EtherType)
- */
-
- uip_input(&priv->dev);
-
- /* If the above function invocation resulted in data that should be
- * sent out on the network, the field d_len will set to a value > 0.
- */
-
- if (priv->dev.d_len > 0)
- {
- slip_transmit(priv);
- }
-}
-
-/****************************************************************************
* Function: slip_rxtask
*
* Description:
@@ -608,10 +566,8 @@ static inline void slip_receive(FAR struct slip_driver_s *priv)
static int slip_rxtask(int argc, char *argv[])
{
FAR struct slip_driver_s *priv;
- struct pollfd fds[1];
unsigned int index = *(argv[1]) - '0';
- irqstate_t flags;
- int ret;
+ int ch;
ndbg("index: %d\n", index);
DEBUGASSERT(index < CONFIG_SLIP_NINTERFACES);
@@ -625,27 +581,79 @@ static int slip_rxtask(int argc, char *argv[])
for (;;)
{
- /* Set up the poll */
+ /* Wait for the next character to be available on the input stream. */
- memset(fds, 0, sizeof(struct pollfd));
- fds[0].fd = priv->fd;
- fds[0].events = POLLIN;
- fds[0].revents = 0;
+ ch = slip_getc(priv);
+
+ /* We have something... three interesting cases. First there might
+ * be a read error. Anything other an EINTR would indicate a serious
+ * device-related problem or software bug.
+ */
- /* Wait for incoming data (with no timeout) */
+ if (ch == EOF)
+ {
+ DEBUGASSERT(errno == EINTR);
+ continue;
+ }
+
+ /* END characters may appear at packet boundaries BEFORE as well as
+ * after the beginning of the packet. This is normal and expected.
+ */
- ret = poll(fds, 1, -1);
- DEBUGASSERT(ret >= 0);
- if (ret > 0)
+ else if (ch == SLIP_END)
{
- /* Call slip_receive() to handle incoming data. Interrupts must
- * be disabled here to keept the POLL watchdoe from firing.
+ priv->rxlen = 0;
+ }
+
+ /* Otherwise, we are in danger of being out-of-sync. Apparently the
+ * leading END character is optional. Let's try to continue.
+ */
+
+ else
+ {
+ priv->rxbuf[0] = (uint8_t)ch;
+ priv->rxlen = 1;
+ }
+
+ /* Copy the data data from the hardware to priv->rxbuf until we put
+ * together a whole packet.
+ */
+
+ slip_receive(priv);
+ SLIP_STAT(priv, received);
+
+ /* All packets are assumed to be IP packets (we don't have a choice..
+ * there is no Ethernet header containing the EtherType). So pass the
+ * received packet on for IP processing -- but only if it is big
+ * enough to hold an IP header.
+ */
+
+ if (priv->rxlen >= UIP_IPH_LEN)
+ {
+ /* Handle the IP input. Interrupts must be disabled here to
+ * keep the POLL watchdog from firing.
+ */
+
+ irqstate_t flags = irqsave();
+ priv->dev.d_buf = priv->rxbuf;
+ priv->dev.d_len = priv->rxlen;
+ uip_input(&priv->dev);
+
+ /* If the above function invocation resulted in data that should
+ * be sent out on the network, the field d_len will set to a
+ * value > 0. NOTE that we are transmitting using the RX buffer!
*/
- flags = irqsave();
- slip_receive(priv);
+ if (priv->dev.d_len > 0)
+ {
+ slip_transmit(priv);
+ }
irqrestore(flags);
}
+ else
+ {
+ SLIP_STAT(priv, rxsmallpacket);
+ }
}
/* We won't get here */
@@ -677,6 +685,7 @@ static void slip_polltimer(int argc, uint32_t arg, ...)
/* If so, update TCP timing states and poll uIP for new XMIT data. */
+ priv->dev.d_buf = priv->txbuf;
(void)uip_timer(&priv->dev, slip_uiptxpoll, SLIP_POLLHSEC);
/* Setup the watchdog poll timer again */
@@ -791,6 +800,7 @@ static int slip_txavail(struct uip_driver_s *dev)
{
/* Poll uIP for new XMIT data */
+ priv->dev.d_buf = priv->txbuf;
(void)uip_poll(&priv->dev, slip_uiptxpoll);
}
@@ -881,8 +891,8 @@ static int slip_rmmac(struct uip_driver_s *dev, FAR const uint8_t *mac)
int slip_initialize(int intf, const char *devname)
{
struct slip_driver_s *priv;
- char buffer[IFNAMSIZ];
- pid_t pid;
+ char buffer[8];
+ const char *argv[2];
/* Get the interface structure associated with this interface number. */
@@ -903,18 +913,10 @@ int slip_initialize(int intf, const char *devname)
/* Open the device */
- priv->fd = open(devname, O_RDWR, 0666);
- if (priv->fd < 0)
- {
- ndbg("ERROR: Failed to open %s: %d\n", devname, errno);
- return -errno;
- }
-
- priv->stream = fdopen(priv->fd, "rw");
+ priv->stream = fopen(devname, "rw");
if (priv->stream == NULL)
{
ndbg("ERROR: Failed to fdopen %s: %d\n", devname, errno);
- close(priv->fd);
return -errno;
}
@@ -930,16 +932,18 @@ int slip_initialize(int intf, const char *devname)
/* Start the SLIP receiver task */
- snprintf(buffer, IFNAMSIZ, "%d", intf);
+ snprintf(buffer, 8, "%d", intf);
+ argv[0] = buffer;
+ argv[1] = NULL;
#ifndef CONFIG_CUSTOM_STACK
- pid = task_create("usbhost", CONFIG_SLIP_DEFPRIO, CONFIG_SLIP_STACKSIZE,
- (main_t)slip_rxtask, (const char **)buffer);
+ priv->pid = task_create("usbhost", CONFIG_SLIP_DEFPRIO,
+ CONFIG_SLIP_STACKSIZE, (main_t)slip_rxtask, argv);
#else
- pid = task_create("usbhost", CONFIG_SLIP_DEFPRIO,
- (main_t)slip_rxtask, (const char **)buffer);
+ priv->pid = task_create("usbhost", CONFIG_SLIP_DEFPRIO,
+ (main_t)slip_rxtask, argv);
#endif
- if (pid < 0)
+ if (priv->pid < 0)
{
ndbg("ERROR: Failed to start receiver task\n");
return -errno;
@@ -956,7 +960,7 @@ int slip_initialize(int intf, const char *devname)
/* Register the device with the OS so that socket IOCTLs can be performed */
#if CONFIG_NSOCKET_DESCRIPTORS > 0
- snprintf(buffer, IFNAMSIZ, "slip%d", intf);
+ snprintf(priv->dev.d_ifname, IFNAMSIZ, "slip%d", intf);
#endif
(void)netdev_register(&priv->dev);
return OK;
diff --git a/nuttx/include/net/uip/uip-arch.h b/nuttx/include/net/uip/uip-arch.h
index 49608de49..2cbe7239c 100644
--- a/nuttx/include/net/uip/uip-arch.h
+++ b/nuttx/include/net/uip/uip-arch.h
@@ -102,33 +102,23 @@ struct uip_driver_s
uip_ipaddr_t d_draddr; /* Default router IP address */
uip_ipaddr_t d_netmask; /* Network subnet mask */
- /* The d_buf array is used to hold incoming and outgoing
- * packets. The device driver should place incoming data into this
- * buffer. When sending data, the device driver should read the link
- * level headers and the TCP/IP headers from this buffer. The size of
- * the link level headers is configured by the UIP_LLH_LEN define.
+ /* The d_buf array is used to hold incoming and outgoing packets. The device
+ * driver should place incoming data into this buffer. When sending data,
+ * the device driver should read the link level headers and the TCP/IP
+ * headers from this buffer. The size of the link level headers is
+ * configured by the UIP_LLH_LEN define.
*
- * Note: The application data need not be placed in this buffer, so
- * the device driver must read it from the place pointed to by the
- * d_appdata pointer as illustrated by the following example:
- *
- * void
- * devicedriver_send(void)
- * {
- * hwsend(&dev->d_buf[0], UIP_LLH_LEN);
- * if(dev->d_len <= UIP_LLH_LEN + UIP_TCPIP_HLEN)
- * {
- * hwsend(&dev->d_buf[UIP_LLH_LEN], dev->d_len - UIP_LLH_LEN);
- * }
- * else
- * {
- * hwsend(&dev->d_buf[UIP_LLH_LEN], UIP_TCPIP_HLEN);
- * hwsend(dev->d_appdata, dev->d_len - UIP_TCPIP_HLEN - UIP_LLH_LEN);
- * }
- * }
+ * uIP will handle only a single buffer for both incoming and outgoing
+ * packets. However, the drive design may be concurrently send and
+ * filling separate, break-off buffers if CONFIG_NET_MULTIBUFFER is
+ * defined. That buffer management must be controlled by the driver.
*/
+#ifdef CONFIG_NET_MULTIBUFFER
+ uint8_t *d_buf;
+#else
uint8_t d_buf[CONFIG_NET_BUFSIZE + 2];
+#endif
/* d_appdata points to the location where application data can be read from
* or written into a packet.
diff --git a/nuttx/lib/lib_fopen.c b/nuttx/lib/lib_fopen.c
index 6502f0ee4..e198ce888 100644
--- a/nuttx/lib/lib_fopen.c
+++ b/nuttx/lib/lib_fopen.c
@@ -1,7 +1,7 @@
/****************************************************************************
* lib/lib_fopen.c
*
- * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* Redistribution and use in source and binary forms, with or without
@@ -251,15 +251,34 @@ FAR FILE *fdopen(int fd, FAR const char *mode)
FAR FILE *fopen(FAR const char *path, FAR const char *mode)
{
- FAR struct filelist *flist = sched_getfiles();
- FAR struct streamlist *slist = sched_getstreams();
- int oflags = lib_mode2oflags(mode);
- int fd = open(path, oflags, 0666);
+ FAR FILE *ret = NULL;;
+ int oflags;
+ int fd;
+
+ /* Open the file */
+
+ oflags = lib_mode2oflags(mode);
+ fd = open(path, oflags, 0666);
+
+ /* If the open was successful, then fdopen() the fil using the file
+ * desciptor returned by open. If open failed, then just return the
+ * NULL stream -- open() has already set the errno.
+ */
- FAR FILE *ret = lib_fdopen(fd, mode, flist, slist);
- if (!ret)
+ if (fd >= 0)
{
- (void)close(fd);
+ FAR struct filelist *flist = sched_getfiles();
+ FAR struct streamlist *slist = sched_getstreams();
+
+ ret = lib_fdopen(fd, mode, flist, slist);
+ if (!ret)
+ {
+ /* Don't forget to close the file descriptor if any other
+ * failures are reported by fdopen().
+ */
+
+ (void)close(fd);
+ }
}
return ret;
}