summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2015-02-10 14:04:08 -0600
committerGregory Nutt <gnutt@nuttx.org>2015-02-10 14:04:08 -0600
commitc1a49b010c53d5d7aca3924b80fd843d3750107d (patch)
tree763e3dcb063bbac82a554dcc2de5776ba042f49f
parentbfece6b55cbc0829f607ef3d60bfb941113dc95c (diff)
downloadnuttx-c1a49b010c53d5d7aca3924b80fd843d3750107d.tar.gz
nuttx-c1a49b010c53d5d7aca3924b80fd843d3750107d.tar.bz2
nuttx-c1a49b010c53d5d7aca3924b80fd843d3750107d.zip
LPC17xx: Add IPv6 support to the LPC17 Ethernet driver. Untested... I no longer have a proper environment for LPC17 debug.
-rw-r--r--nuttx/arch/arm/src/lpc17xx/lpc17_emacram.h4
-rw-r--r--nuttx/arch/arm/src/lpc17xx/lpc17_ethernet.c293
-rwxr-xr-xnuttx/configs/olimex-lpc1766stk/nettest/setenv.sh5
3 files changed, 289 insertions, 13 deletions
diff --git a/nuttx/arch/arm/src/lpc17xx/lpc17_emacram.h b/nuttx/arch/arm/src/lpc17xx/lpc17_emacram.h
index 16a3b00c1..ec332b4f9 100644
--- a/nuttx/arch/arm/src/lpc17xx/lpc17_emacram.h
+++ b/nuttx/arch/arm/src/lpc17xx/lpc17_emacram.h
@@ -60,7 +60,7 @@
#endif
/* Is networking enabled? Is the LPC17xx Ethernet device enabled? Does this chip have
- * and Ethernet controlloer? Yes... then we will replace the above default definitions.
+ * and Ethernet controller? Yes... then we will replace the above default definitions.
*/
#if defined(CONFIG_NET) && defined(CONFIG_LPC17_ETHERNET) && LPC17_NETHCONTROLLERS > 0
@@ -124,7 +124,7 @@
/* EMAC DMA RAM and descriptor definitions. The configured number of descriptors
* will determine the organization and the size of the descriptor and status tables.
* There is a complex interaction between the maximum packet size (CONFIG_NET_ETH_MTU)
- * and the number of Rx and Tx descriptors that can be suppored (CONFIG_NET_NRXDESC
+ * and the number of Rx and Tx descriptors that can be supported (CONFIG_NET_NRXDESC
* and CONFIG_NET_NTXDESC): Small buffers -> more packets. This is something that
* needs to be tuned for you system.
*
diff --git a/nuttx/arch/arm/src/lpc17xx/lpc17_ethernet.c b/nuttx/arch/arm/src/lpc17xx/lpc17_ethernet.c
index fdda0fe4c..c13dc2473 100644
--- a/nuttx/arch/arm/src/lpc17xx/lpc17_ethernet.c
+++ b/nuttx/arch/arm/src/lpc17xx/lpc17_ethernet.c
@@ -361,11 +361,17 @@ static void lpc17_txtimeout(int argc, uint32_t arg, ...);
/* NuttX callback functions */
+#ifdef CONFIG_NET_ICMPv6
+static void lpc17_ipv6multicast(FAR struct lpc17_ethmac_s *priv);
+#endif
static int lpc17_ifup(struct net_driver_s *dev);
static int lpc17_ifdown(struct net_driver_s *dev);
static int lpc17_txavail(struct net_driver_s *dev);
-#ifdef CONFIG_NET_IGMP
+#if defined(CONFIG_NET_IGMP) || defined(CONFIG_NET_ICMPv6)
+static uint32_t lpc17_calcethcrc(const uint8_t *data, size_t length);
static int lpc17_addmac(struct net_driver_s *dev, const uint8_t *mac);
+#endif
+#ifdef CONFIG_NET_IGMP
static int lpc17_rmmac(struct net_driver_s *dev, const uint8_t *mac);
#endif
@@ -1423,6 +1429,79 @@ static void lpc17_polltimer(int argc, uint32_t arg, ...)
}
/****************************************************************************
+ * Function: lpc17_ipv6multicast
+ *
+ * Description:
+ * Configure the IPv6 multicast MAC address.
+ *
+ * Parameters:
+ * priv - A reference to the private driver state structure
+ *
+ * Returned Value:
+ * OK on success; Negated errno on failure.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_ICMPv6
+static void lpc17_ipv6multicast(FAR struct lpc17_ethmac_s *priv)
+{
+ struct net_driver_s *dev;
+ uint16_t tmp16;
+ uint8_t mac[6];
+
+ /* For ICMPv6, we need to add the IPv6 multicast address
+ *
+ * For IPv6 multicast addresses, the Ethernet MAC is derived by
+ * the four low-order octets OR'ed with the MAC 33:33:00:00:00:00,
+ * so for example the IPv6 address FF02:DEAD:BEEF::1:3 would map
+ * to the Ethernet MAC address 33:33:00:01:00:03.
+ *
+ * NOTES: This appears correct for the ICMPv6 Router Solicitation
+ * Message, but the ICMPv6 Neighbor Solicitation message seems to
+ * use 33:33:ff:01:00:03.
+ */
+
+ mac[0] = 0x33;
+ mac[1] = 0x33;
+
+ dev = &priv->dev;
+ tmp16 = dev->d_ipv6addr[6];
+ mac[2] = 0xff;
+ mac[3] = tmp16 >> 8;
+
+ tmp16 = dev->d_ipv6addr[7];
+ mac[4] = tmp16 & 0xff;
+ mac[5] = tmp16 >> 8;
+
+ nvdbg("IPv6 Multicast: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+ (void)lpc17_addmac(dev, mac);
+
+#ifdef CONFIG_NET_ICMPv6_AUTOCONF
+ /* Add the IPv6 all link-local nodes Ethernet address. This is the
+ * address that we expect to receive ICMPv6 Router Advertisement
+ * packets.
+ */
+
+ (void)lpc17_addmac(dev, g_ipv6_ethallnodes.ether_addr_octet);
+
+#endif /* CONFIG_NET_ICMPv6_AUTOCONF */
+#ifdef CONFIG_NET_ICMPv6_ROUTER
+ /* Add the IPv6 all link-local routers Ethernet address. This is the
+ * address that we expect to receive ICMPv6 Router Solicitation
+ * packets.
+ */
+
+ (void)lpc17_addmac(dev, g_ipv6_ethallrouters.ether_addr_octet);
+
+#endif /* CONFIG_NET_ICMPv6_ROUTER */
+}
+#endif /* CONFIG_NET_ICMPv6 */
+
+/****************************************************************************
* Function: lpc17_ifup
*
* Description:
@@ -1476,6 +1555,12 @@ static int lpc17_ifup(struct net_driver_s *dev)
(uint32_t)priv->lp_dev.d_mac.ether_addr_octet[0];
lpc17_putreg(regval, LPC17_ETH_SA2);
+#ifdef CONFIG_NET_ICMPv6
+ /* Set up the IPv6 multicast address */
+
+ lpc17_ipv6multicast(priv);
+#endif
+
/* Initialize Ethernet interface for the PHY setup */
lpc17_macmode(priv->lp_mode);
@@ -1686,6 +1771,99 @@ static int lpc17_txavail(struct net_driver_s *dev)
}
/****************************************************************************
+ * Function: lpc17_calcethcrc
+ *
+ * Description:
+ * Function to calculate the CRC used by LPC17 to check an Ethernet frame
+ *
+ * Algorithm adapted from LPC17xx sample code that contains this notice:
+ *
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ *
+ * Parameters:
+ * data - the data to be checked
+ * length - length of the data
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_NET_IGMP) || defined(CONFIG_NET_ICMPv6)
+static uint32_t lpc17_calcethcrc(const uint8_t *data, size_t length)
+{
+ char byte;
+ int crc;
+ int q0;
+ int q1;
+ int q2;
+ int q3;
+ int i;
+ int j;
+
+ crc = 0xffffffff;
+ for (i = 0; i < frame_len; i++)
+ {
+ byte = *frame_no_fcs++;
+ for (j = 0; j < 2; j++)
+ {
+ if (((crc >> 28) ^ (byte >> 3)) & 0x00000001)
+ {
+ q3 = 0x04c11db7;
+ }
+ else
+ {
+ q3 = 0x00000000;
+ }
+
+ if (((crc >> 29) ^ (byte >> 2)) & 0x00000001)
+ {
+ q2 = 0x09823b6e;
+ }
+ else
+ {
+ q2 = 0x00000000;
+ }
+
+ if (((crc >> 30) ^ (byte >> 1)) & 0x00000001)
+ {
+ q1 = 0x130476dc;
+ }
+ else
+ {
+ q1 = 0x00000000;
+ }
+
+ if (((crc >> 31) ^ (byte >> 0)) & 0x00000001)
+ {
+ q0 = 0x2608EDB8;
+ }
+ else
+ {
+ q0 = 0x00000000;
+ }
+
+ crc = (crc << 4) ^ q3 ^ q2 ^ q1 ^ q0;
+ byte >>= 4;
+ }
+ }
+
+ return crc;
+}
+#endif /* CONFIG_NET_IGMP || CONFIG_NET_ICMPv6 */
+
+/****************************************************************************
* Function: lpc17_addmac
*
* Description:
@@ -1703,17 +1881,62 @@ static int lpc17_txavail(struct net_driver_s *dev)
*
****************************************************************************/
-#ifdef CONFIG_NET_IGMP
+#if defined(CONFIG_NET_IGMP) || defined(CONFIG_NET_ICMPv6)
static int lpc17_addmac(struct net_driver_s *dev, const uint8_t *mac)
{
- struct lpc17_driver_s *priv = (struct lpc17_driver_s *)dev->d_private;
+ uintptr_t regaddr;
+ uint32_t regval;
+ uint32_t crc;
+ unsigned int ndx;
+
+ nllvdbg("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+ /* Hash function:
+ *
+ * The standard Ethernet cyclic redundancy check (CRC) function is
+ * calculated from the 6 byte MAC address. Bits [28:23] out of the 32-bit
+ * CRC result are taken to form the hash. The 6-bit hash is used to access
+ * the hash table: it is used as an index in the 64-bit HashFilter register
+ * that has been programmed with accept values. If the selected accept value
+ * is 1, the frame is accepted.
+ */
+
+ crc = lpc17_calcethcrc(mac, 6);
+ ndx = (crc >> 23) & 0x3f;
- /* Add the MAC address to the hardware multicast routing table */
+ /* Add the MAC address to the hardware multicast hash table */
+
+ if (ndx > 31)
+ {
+ regaddr = LPC17_ETH_HASHFLH; /* Hash filter table MSBs register */
+ ndx -= 32;
+ }
+ else
+ {
+ regaddr = LPC17_ETH_HASHFLL; /* Hash filter table LSBs register */
+ }
+
+ regval = lpc17_getreg(regaddr);
+ regval |= 1 << ndx;
+ lpc17_putreg(regval, regaddr);
+
+ /* Enabled multicast address filtering in the RxFilterControl register:
+ *
+ * AcceptUnicastHashEn: When set to ’1’, unicast frames that pass the
+ * imperfect hash filter are accepted.
+ * AcceptMulticastHashEn When set to ’1’, multicast frames that pass the
+ * imperfect hash filter are accepted.
+ */
+
+ regval = lpc17_getreg(LPC17_ETH_RXFLCTRL);
+ regval &= ~ETH_RXFLCTRL_UCASTHASHEN;
+ regval |= ETH_RXFLCTRL_MCASTHASHEN;
+ lpc17_putreg(regval, LPC17_ETH_RXFLCTRL);
-#warning "Not implemented"
return OK;
}
-#endif
+#endif /* CONFIG_NET_IGMP || CONFIG_NET_ICMPv6 */
/****************************************************************************
* Function: lpc17_rmmac
@@ -1736,11 +1959,63 @@ static int lpc17_addmac(struct net_driver_s *dev, const uint8_t *mac)
#ifdef CONFIG_NET_IGMP
static int lpc17_rmmac(struct net_driver_s *dev, const uint8_t *mac)
{
- struct lpc17_driver_s *priv = (struct lpc17_driver_s *)dev->d_private;
+ uintptr_t regaddr1;
+ uintptr_t regaddr2;
+ uint32_t regval;
+ uint32_t crc;
+ unsigned int ndx;
+
+ nllvdbg("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+ /* Hash function:
+ *
+ * The standard Ethernet cyclic redundancy check (CRC) function is
+ * calculated from the 6 byte MAC address. Bits [28:23] out of the 32-bit
+ * CRC result are taken to form the hash. The 6-bit hash is used to access
+ * the hash table: it is used as an index in the 64-bit HashFilter register
+ * that has been programmed with accept values. If the selected accept value
+ * is 1, the frame is accepted.
+ */
+
+ crc = lpc17_calcethcrc(mac, 6);
+ ndx = (crc >> 23) & 0x3f;
+
+ /* Remove the MAC address to the hardware multicast hash table */
+
+ if (ndx > 31)
+ {
+ regaddr1 = LPC17_ETH_HASHFLH; /* Hash filter table MSBs register */
+ regaddr2 = LPC17_ETH_HASHFLL; /* Hash filter table LSBs register */
+ ndx -= 32;
+ }
+ else
+ {
+ regaddr1 = LPC17_ETH_HASHFLL; /* Hash filter table LSBs register */
+ regaddr2 = LPC17_ETH_HASHFLH; /* Hash filter table MSBs register */
+ }
+
+ regval = lpc17_getreg(regaddr1);
+ regval &= ~(1 << ndx);
+ lpc17_putreg(regval, regaddr1);
+
+ /* If there are no longer addresses being filtered , disable multicast
+ * filtering.
+ */
- /* Add the MAC address to the hardware multicast routing table */
+ if (regval == 0 && lpc17_getreg(regaddr2) == 0)
+ {
+ /* AcceptUnicastHashEn: When set to ’1’, unicast frames that pass the
+ * imperfect hash filter are accepted.
+ * AcceptMulticastHashEn When set to ’1’, multicast frames that pass the
+ * imperfect hash filter are accepted.
+ */
+
+ regval = lpc17_getreg(LPC17_ETH_RXFLCTRL);
+ regval &= ~(ETH_RXFLCTRL_UCASTHASHEN | ETH_RXFLCTRL_MCASTHASHEN);
+ lpc17_putreg(regval, LPC17_ETH_RXFLCTRL);
+ }
-#warning "Not implemented"
return OK;
}
#endif
diff --git a/nuttx/configs/olimex-lpc1766stk/nettest/setenv.sh b/nuttx/configs/olimex-lpc1766stk/nettest/setenv.sh
index 551e4042d..1a1fb344b 100755
--- a/nuttx/configs/olimex-lpc1766stk/nettest/setenv.sh
+++ b/nuttx/configs/olimex-lpc1766stk/nettest/setenv.sh
@@ -50,8 +50,9 @@ fi
# This is the Cygwin path to the location where I installed the CodeSourcery
# toolchain under windows. You will also have to edit this if you install
# the CodeSourcery toolchain in any other location
-# export TOOLCHAIN_BIN="/cygdrive/c/Program Files (x86)/CodeSourcery/Sourcery G++ Lite/bin"
-# export TOOLCHAIN_BIN="/cygdrive/c/Program Files (x86)/CodeSourcery/Sourcery_CodeBench_Lite_for_ARM_EABI/bin"
+#export TOOLCHAIN_BIN="/cygdrive/c/Program Files (x86)/CodeSourcery/Sourcery G++ Lite/bin"
+#export TOOLCHAIN_BIN="/cygdrive/c/Program Files (x86)/CodeSourcery/Sourcery_CodeBench_Lite_for_ARM_EABI/bin"
+#export TOOLCHAIN_BIN="/cygdrive/c/Users/MyName/MentorGraphics/Sourcery_CodeBench_Lite_for_ARM_EABI/bin"
# These are the Cygwin paths to the locations where I installed the Atollic
# toolchain under windows. You will also have to edit this if you install