Networking: SLIP interface improvements. From Macs N.

This commit is contained in:
Gregory Nutt
2015-01-30 08:09:38 -06:00
parent 3eacc1e486
commit 2f009a2afe
+87 -52
View File
@@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* drivers/net/slip.c * drivers/net/slip.c
* *
* Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. * Copyright (C) 2011-2012, 2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Reference: RFC 1055 * Reference: RFC 1055
@@ -56,6 +56,7 @@
#include <nuttx/irq.h> #include <nuttx/irq.h>
#include <nuttx/net/net.h> #include <nuttx/net/net.h>
#include <nuttx/clock.h>
#include <nuttx/net/netdev.h> #include <nuttx/net/netdev.h>
#include <nuttx/net/ip.h> #include <nuttx/net/ip.h>
#include <nuttx/net/slip.h> #include <nuttx/net/slip.h>
@@ -158,11 +159,12 @@ struct slip_statistics_s
struct slip_driver_s struct slip_driver_s
{ {
volatile bool bifup; /* true:ifup false:ifdown */ volatile bool bifup; /* true:ifup false:ifdown */
int fd; /* TTY file descriptor */ bool txnodelay; /* True: usleep() not needed */
int16_t fd; /* TTY file descriptor */
uint16_t rxlen; /* The number of bytes in rxbuf */
pid_t rxpid; /* Receiver thread ID */ pid_t rxpid; /* Receiver thread ID */
pid_t txpid; /* Transmitter thread ID */ pid_t txpid; /* Transmitter thread ID */
sem_t waitsem; /* Mutually exclusive access to uIP */ sem_t waitsem; /* Mutually exclusive access to uIP */
uint16_t rxlen; /* The number of bytes in rxbuf */
/* Driver statistics */ /* Driver statistics */
@@ -195,7 +197,8 @@ static void slip_semtake(FAR struct slip_driver_s *priv);
/* Common TX logic */ /* Common TX logic */
static void slip_write(FAR struct slip_driver_s *priv, const uint8_t *buffer, int len); static void slip_write(FAR struct slip_driver_s *priv,
FAR const uint8_t *buffer, int len);
static void slip_putc(FAR struct slip_driver_s *priv, int ch); static void slip_putc(FAR struct slip_driver_s *priv, int ch);
static int slip_transmit(FAR struct slip_driver_s *priv); static int slip_transmit(FAR struct slip_driver_s *priv);
static int slip_txpoll(FAR struct net_driver_s *dev); static int slip_txpoll(FAR struct net_driver_s *dev);
@@ -255,7 +258,7 @@ static void slip_semtake(FAR struct slip_driver_s *priv)
****************************************************************************/ ****************************************************************************/
static inline void slip_write(FAR struct slip_driver_s *priv, static inline void slip_write(FAR struct slip_driver_s *priv,
const uint8_t *buffer, int len) FAR const uint8_t *buffer, int len)
{ {
/* Handle the case where the write is awakened by a signal */ /* Handle the case where the write is awakened by a signal */
@@ -390,6 +393,7 @@ static int slip_transmit(FAR struct slip_driver_s *priv)
/* And send the END token */ /* And send the END token */
slip_putc(priv, SLIP_END); slip_putc(priv, SLIP_END);
priv->txnodelay = true;
return OK; return OK;
} }
@@ -454,6 +458,9 @@ static void slip_txtask(int argc, FAR char *argv[])
FAR struct slip_driver_s *priv; FAR struct slip_driver_s *priv;
unsigned int index = *(argv[1]) - '0'; unsigned int index = *(argv[1]) - '0';
net_lock_t flags; net_lock_t flags;
unsigned int msec_start;
unsigned int msec_now;
unsigned int hsec;
ndbg("index: %d\n", index); ndbg("index: %d\n", index);
DEBUGASSERT(index < CONFIG_SLIP_NINTERFACES); DEBUGASSERT(index < CONFIG_SLIP_NINTERFACES);
@@ -467,11 +474,22 @@ static void slip_txtask(int argc, FAR char *argv[])
/* Loop forever */ /* Loop forever */
msec_start = clock_systimer() * MSEC_PER_TICK;
for (;;) for (;;)
{ {
/* Wait for the timeout to expire (or until we are signaled by by */ /* Wait for the timeout to expire (or until we are signaled by by */
usleep(SLIP_WDDELAY); slip_semtake(priv);
if (!priv->txnodelay)
{
slip_semgive(priv);
usleep(SLIP_WDDELAY);
}
else
{
priv->txnodelay = false;
slip_semgive(priv);
}
/* Is the interface up? */ /* Is the interface up? */
@@ -483,15 +501,23 @@ static void slip_txtask(int argc, FAR char *argv[])
slip_semtake(priv); slip_semtake(priv);
/* Poll uIP for new XMIT data. BUG: We really need to calculate /* Poll the networking layer for new XMIT data. */
* the number of hsecs! When we are awakened by slip_txavail, the
* number will be smaller; when we have to wait for the semaphore
* (above), it may be larger.
*/
flags = net_lock(); flags = net_lock();
priv->dev.d_buf = priv->txbuf; priv->dev.d_buf = priv->txbuf;
(void)devif_timer(&priv->dev, slip_txpoll, SLIP_POLLHSEC);
msec_now = clock_systimer() * MSEC_PER_TICK;
hsec = (unsigned int)(msec_now - msec_start) / (MSEC_PER_SEC / 2);
if (hsec)
{
(void)devif_timer(&priv->dev, slip_txpoll, hsec);
msec_start += hsec * (MSEC_PER_SEC / 2);
}
else
{
(void)uip_poll(&priv->dev, slip_uiptxpoll);
}
net_unlock(flags); net_unlock(flags);
slip_semgive(priv); slip_semgive(priv);
} }
@@ -563,19 +589,21 @@ static inline void slip_receive(FAR struct slip_driver_s *priv)
*/ */
case SLIP_END: case SLIP_END:
nvdbg("END\n"); {
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,
* it. This is meant to avoid bothering IP with all the empty * ignore it. This is meant to avoid bothering IP with all the
* packets generated by the duplicate END characters which are in * empty packets generated by the duplicate END characters which
* turn sent to try to detect line noise. * are in turn sent to try to detect line noise.
*/ */
if (priv->rxlen > 0) if (priv->rxlen > 0)
{ {
nvdbg("Received packet size %d\n", priv->rxlen); nvdbg("Received packet size %d\n", priv->rxlen);
return; return;
} }
}
break; break;
/* if it's the same code as an ESC character, wait and get another /* if it's the same code as an ESC character, wait and get another
@@ -584,38 +612,44 @@ static inline void slip_receive(FAR struct slip_driver_s *priv)
*/ */
case SLIP_ESC: case SLIP_ESC:
nvdbg("ESC\n"); {
ch = slip_getc(priv); nvdbg("ESC\n");
ch = slip_getc(priv);
/* if "ch" is not one of these two, then we have a protocol /* if "ch" is not one of these two, then we have a protocol
* violation. The best bet seems to be to leave the byte alone * violation. The best bet seems to be to leave the byte alone
* and just stuff it into the packet * and just stuff it into the packet
*/ */
switch (ch) switch (ch)
{ {
case SLIP_ESC_END: case SLIP_ESC_END:
nvdbg("ESC-END\n"); nvdbg("ESC-END\n");
ch = SLIP_END; ch = SLIP_END;
break; break;
case SLIP_ESC_ESC:
nvdbg("ESC-ESC\n");
ch = SLIP_ESC;
break;
default:
ndbg("ERROR: Protocol violation: %02x\n", ch);
break;
}
/* Here we fall into the default handler and let it store the case SLIP_ESC_ESC:
* character for us nvdbg("ESC-ESC\n");
*/ ch = SLIP_ESC;
break;
default:
ndbg("ERROR: Protocol violation: %02x\n", ch);
break;
}
/* Here we fall into the default handler and let it store the
* character for us
*/
}
default: default:
if (priv->rxlen < CONFIG_NET_SLIP_MTU+2) {
{ if (priv->rxlen < CONFIG_NET_SLIP_MTU+2)
priv->rxbuf[priv->rxlen++] = ch; {
} priv->rxbuf[priv->rxlen++] = ch;
}
}
break; break;
} }
} }
@@ -724,6 +758,7 @@ static int slip_rxtask(int argc, FAR char *argv[])
if (priv->dev.d_len > 0) if (priv->dev.d_len > 0)
{ {
slip_transmit(priv); slip_transmit(priv);
kill(priv->txpid, SIGALRM);
} }
net_unlock(flags); net_unlock(flags);
slip_semgive(priv); slip_semgive(priv);
@@ -822,6 +857,7 @@ static int slip_txavail(FAR struct net_driver_s *dev)
{ {
/* Wake up the TX polling thread */ /* Wake up the TX polling thread */
priv->txnodelay = true;
kill(priv->txpid, SIGALRM); kill(priv->txpid, SIGALRM);
} }
@@ -912,7 +948,7 @@ int slip_initialize(int intf, FAR const char *devname)
{ {
FAR struct slip_driver_s *priv; FAR struct slip_driver_s *priv;
char buffer[8]; char buffer[8];
FAR const char *argv[2]; FAR char *argv[2];
/* Get the interface structure associated with this interface number. */ /* Get the interface structure associated with this interface number. */
@@ -1002,4 +1038,3 @@ int slip_initialize(int intf, FAR const char *devname)
} }
#endif /* CONFIG_NET && CONFIG_NET_SLIP */ #endif /* CONFIG_NET && CONFIG_NET_SLIP */