mirror of
https://github.com/apache/nuttx.git
synced 2026-09-24 00:42:03 +08:00
arch/arm/src/lpc54xx: Correct handling of the Ethernet RBU error. With this fix, Ethernet now appears to be fully functional although still undertested.
This commit is contained in:
@@ -300,7 +300,7 @@
|
||||
# define ETH_MAC_FRAME_FILTER_PCF_FILTERED (3 << ETH_MAC_FRAME_FILTER_PCF_SHIFT) /* Control frames accepted if pass the address filter */
|
||||
#define ETH_MAC_FRAME_FILTER_SAIF (1 << 8) /* Bit 8: SA inverse filtering */
|
||||
#define ETH_MAC_FRAME_FILTER_SAF (1 << 9) /* Bit 9: Source address filter enable */
|
||||
#define ETH_MAC_FRAME_FILTER_RA (1 << 31) /* Bit 31: Receive all */
|
||||
#define ETH_MAC_FRAME_FILTER_RA (1 << 31) /* Bit 31: Receive all */
|
||||
|
||||
/* MAC watchdog timeout */
|
||||
#define ETH_MAC_WD_TIMEROUT_
|
||||
|
||||
@@ -368,7 +368,7 @@ static uint32_t lpc54_getreg(uintptr_t addr);
|
||||
static void lpc54_putreg(uint32_t val, uintptr_t addr);
|
||||
#else
|
||||
# define lpc54_getreg(addr) getreg32(addr)
|
||||
# define lpc54_putreg(val,addr) lpc54_putreg(val,addr)
|
||||
# define lpc54_putreg(val,addr) putreg32(val,addr)
|
||||
#endif
|
||||
|
||||
/* Common TX logic */
|
||||
@@ -381,7 +381,7 @@ static int lpc54_eth_txpoll(struct net_driver_s *dev);
|
||||
/* Interrupt handling */
|
||||
|
||||
static void lpc54_eth_rxdisptch(struct lpc54_ethdriver_s *priv);
|
||||
static void lpc54_eth_receive(struct lpc54_ethdriver_s *priv,
|
||||
static int lpc54_eth_receive(struct lpc54_ethdriver_s *priv,
|
||||
unsigned int chan);
|
||||
static void lpc54_eth_txdone(struct lpc54_ethdriver_s *priv,
|
||||
unsigned int chan);
|
||||
@@ -1020,14 +1020,14 @@ static void lpc54_eth_rxdisptch(struct lpc54_ethdriver_s *priv)
|
||||
* chan - The channel with the completed Rx transfer
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
* The number of Rx descriptors processed
|
||||
*
|
||||
* Assumptions:
|
||||
* The network is locked.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void lpc54_eth_receive(struct lpc54_ethdriver_s *priv,
|
||||
static int lpc54_eth_receive(struct lpc54_ethdriver_s *priv,
|
||||
unsigned int chan)
|
||||
{
|
||||
struct lpc54_rxring_s *rxring;
|
||||
@@ -1036,8 +1036,8 @@ static void lpc54_eth_receive(struct lpc54_ethdriver_s *priv,
|
||||
unsigned int pktlen;
|
||||
unsigned int supply;
|
||||
uint32_t regval;
|
||||
bool lastframe = false;
|
||||
bool suspend;
|
||||
int ndesc;
|
||||
|
||||
/* Get the Rx ring associated with this channel */
|
||||
|
||||
@@ -1048,16 +1048,31 @@ static void lpc54_eth_receive(struct lpc54_ethdriver_s *priv,
|
||||
regval = lpc54_getreg(LPC54_ETH_DMACH_STAT(chan));
|
||||
suspend = ((regval & ETH_DMACH_INT_RBU) != 0);
|
||||
|
||||
/* Loop until the last received frame is encountered */
|
||||
/* Loop until the next full frame is encountered or until we encounter a
|
||||
* descriptor still owned by the DMA.
|
||||
*/
|
||||
|
||||
pktlen = 0;
|
||||
while (!lastframe)
|
||||
ndesc = 0;
|
||||
|
||||
for (; ; )
|
||||
{
|
||||
/* Get the last Rx descriptor in the ring */
|
||||
|
||||
supply = rxring->rr_supply;
|
||||
rxdesc = rxring->rr_desc + supply;
|
||||
|
||||
/* Is this frame still owned by the DMA? */
|
||||
|
||||
if ((rxdesc->ctrl & ETH_RXDES3_OWN) != 0)
|
||||
{
|
||||
/* Yes.. then bail */
|
||||
|
||||
return ndesc;
|
||||
}
|
||||
|
||||
ndesc++;
|
||||
|
||||
/* Set the supplier index to the next descriptor */
|
||||
|
||||
if (++(rxring->rr_supply) > rxring->rr_ndesc)
|
||||
@@ -1067,7 +1082,7 @@ static void lpc54_eth_receive(struct lpc54_ethdriver_s *priv,
|
||||
|
||||
/* Is this the last descriptor of the frame? */
|
||||
|
||||
if (rxdesc->ctrl & ETH_RXDES3_LD)
|
||||
if ((rxdesc->ctrl & ETH_RXDES3_LD) != 0)
|
||||
{
|
||||
/* Have we been discarding Rx data? If so, that was the last
|
||||
* packet to be discarded.
|
||||
@@ -1081,10 +1096,9 @@ static void lpc54_eth_receive(struct lpc54_ethdriver_s *priv,
|
||||
{
|
||||
/* Last frame encountered. This is a valid packet */
|
||||
|
||||
lastframe = true;
|
||||
framelen = (rxdesc->ctrl & ETH_RXDES3_PL_MASK);
|
||||
pktlen += framelen;
|
||||
|
||||
pktlen += framelen;
|
||||
if (pktlen > 0)
|
||||
{
|
||||
/* Recover the buffer.
|
||||
@@ -1138,6 +1152,8 @@ static void lpc54_eth_receive(struct lpc54_ethdriver_s *priv,
|
||||
#endif
|
||||
rxdesc->ctrl = regval;
|
||||
}
|
||||
|
||||
return ndesc;
|
||||
}
|
||||
}
|
||||
else if (!priv->eth_rxdiscard)
|
||||
@@ -1162,15 +1178,23 @@ static void lpc54_eth_receive(struct lpc54_ethdriver_s *priv,
|
||||
}
|
||||
}
|
||||
|
||||
/* Restart the receiver if it was suspended. */
|
||||
/* Restart the receiver and clear the RBU status if it was suspended. */
|
||||
|
||||
if (suspend)
|
||||
{
|
||||
uintptr_t regaddr = LPC54_ETH_DMACH_RXDESC_TAIL_PTR(chan);
|
||||
|
||||
/* Clear the RBU status */
|
||||
|
||||
lpc54_putreg(ETH_DMACH_INT_RBU, LPC54_ETH_DMACH_STAT(chan));
|
||||
|
||||
/* Writing to the tail pointer register will restart the Rx processing */
|
||||
|
||||
regval = lpc54_getreg(regaddr);
|
||||
lpc54_putreg(regval, regaddr);
|
||||
}
|
||||
|
||||
return ndesc;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -1295,9 +1319,12 @@ static void lpc54_eth_channel_work(struct lpc54_ethdriver_s *priv,
|
||||
|
||||
if ((pending & LPC54_ABNORM_INTMASK) != 0)
|
||||
{
|
||||
/* Acknowledge the normal receive interrupt */
|
||||
/* Acknowledge the abnormal interrupt interrupts except for RBU...
|
||||
* that is a special case where the status will be cleared in
|
||||
* lpc54_eth_receive(). See comments below.
|
||||
*/
|
||||
|
||||
lpc54_putreg(LPC54_ABNORM_INTMASK, regaddr);
|
||||
lpc54_putreg((LPC54_ABNORM_INTMASK & ~ETH_DMACH_INT_RBU), regaddr);
|
||||
|
||||
/* Handle the incoming packet */
|
||||
|
||||
@@ -1316,6 +1343,25 @@ static void lpc54_eth_channel_work(struct lpc54_ethdriver_s *priv,
|
||||
NETDEV_TXERRORS(priv->eth_dev);
|
||||
}
|
||||
|
||||
/* The Receive Buffer Unavailable (RBU) error is a special case. It
|
||||
* means that we have an Rx overrun condition: All of the Rx buffers
|
||||
* have been filled with packet data and there are no Rx descriptors
|
||||
* available to receive the next packet.
|
||||
*
|
||||
* Often RBU is accompanied by RI but we need to force that condition
|
||||
* in all cases. In the case of RBU, we need to perform receive
|
||||
* processing in order to recover from the situation and to resume.
|
||||
*
|
||||
* This is really a configuration problem: It really means that we
|
||||
* have not assigned enough Rx buffers for the environment and
|
||||
* addressing filtering options that we have selected.
|
||||
*/
|
||||
|
||||
if ((pending & ETH_DMACH_INT_RBU) != 0)
|
||||
{
|
||||
pending |= ETH_DMACH_INT_RI;
|
||||
}
|
||||
|
||||
pending &= ~LPC54_ABNORM_INTMASK;
|
||||
}
|
||||
|
||||
@@ -1323,18 +1369,31 @@ static void lpc54_eth_channel_work(struct lpc54_ethdriver_s *priv,
|
||||
|
||||
if ((pending & ETH_DMACH_INT_RI) != 0)
|
||||
{
|
||||
int ndesc;
|
||||
|
||||
/* Acknowledge the normal receive interrupt */
|
||||
|
||||
lpc54_putreg(ETH_DMACH_INT_RI | ETH_DMACH_INT_NI, regaddr);
|
||||
pending &= ~(ETH_DMACH_INT_RI | ETH_DMACH_INT_NI);
|
||||
|
||||
/* Update statistics */
|
||||
/* Loop until all available Rx packets in the ring have been processed */
|
||||
|
||||
NETDEV_RXPACKETS(priv->eth_dev);
|
||||
for (; ; )
|
||||
{
|
||||
/* Dispatch the next packet from the Rx ring */
|
||||
|
||||
/* Handle the incoming packet */
|
||||
ndesc = lpc54_eth_receive(priv, chan);
|
||||
if (ndesc > 0)
|
||||
{
|
||||
/* Update statistics if a packet was dispatched */
|
||||
|
||||
lpc54_eth_receive(priv, chan);
|
||||
NETDEV_RXPACKETS(priv->eth_dev);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for a transmit interrupt */
|
||||
|
||||
@@ -47,8 +47,8 @@ STATUS
|
||||
in receiving the button events, especially when the button is
|
||||
released. But if you do not press the buttons too quickly all events
|
||||
are processed. This, I suspect, is a consequence of the strong glitch
|
||||
filtering that is enbled in the pin configuration. Snappier
|
||||
response my be obtainble with filtering off.
|
||||
filtering that is enabled in the pin configuration. Snappier
|
||||
response my be obtainable with filtering off.
|
||||
2017-12-17: Added a driver for the FT5x06 capacitive, multi-touch
|
||||
controller. Add support logic for the LPCXpresso-LPC54528 to
|
||||
initialize and the register the FT5x06 driver. Unfortunately, the
|
||||
@@ -84,11 +84,13 @@ STATUS
|
||||
access timing in some way???
|
||||
2017-12-30: Completed implementation of an Ethernet driver. Untested as
|
||||
of this writing. Also added the netnsh configuration will, eventually,
|
||||
be used to test the Ethernet diver.
|
||||
be used to test the Ethernet driver.
|
||||
2018-01-01: There Ethernet driver appears to be fully functional although
|
||||
more testing is certainly needed.
|
||||
|
||||
There is still no support for the Accelerometer, SPIFI, or USB. There are
|
||||
complete but not-yet-functional SD card and Ethernet drivers. There is a
|
||||
partial SPI driver, but no on-board SPI devices to test it.
|
||||
There is still no support for the Accelerometer, SPIFI, or USB. There is a
|
||||
complete but not-yet-functional SD card. There is a partial SPI driver,
|
||||
but no on-board SPI devices to test it.
|
||||
|
||||
Configurations
|
||||
==============
|
||||
@@ -223,7 +225,8 @@ Configurations
|
||||
------
|
||||
This is a special version of the NuttShell (nsh) configuration that is
|
||||
tailored for network testing. This version derives from nsh
|
||||
configuration so manhy of the notes apply there except as noted below.
|
||||
configuration so many of the notes there apply here except as noted
|
||||
below.
|
||||
|
||||
NOTES:
|
||||
|
||||
@@ -231,6 +234,9 @@ Configurations
|
||||
and RJ45 network connector. Support is enabled for IPv4, IPv6, TCP/IP,
|
||||
UDP, ICMP, ICMPv6, and ARP.
|
||||
|
||||
The default IP addresses are 10.0.0.2 (IPv4) and fc00::2 (IPv6). You
|
||||
should reconfigure these as appropriate for your test network.
|
||||
|
||||
2. SD card and I2C support are not enabled. The I2C tool application is
|
||||
not enabled
|
||||
|
||||
@@ -248,6 +254,16 @@ Configurations
|
||||
|
||||
nsh> ifup eth0
|
||||
|
||||
6. Telnet is supported, but the Telnet daemon must be started manually
|
||||
like:
|
||||
|
||||
nsh> telnetd ipv4
|
||||
|
||||
Use the argument 'ipv6' to run telnet in the IPv6 address space. With
|
||||
the above command, you can create a remote Telnet session via:
|
||||
|
||||
$ telnet 10.0.0.2
|
||||
|
||||
nsh:
|
||||
|
||||
Configures the NuttShell (nsh) application located at examples/nsh.
|
||||
@@ -354,8 +370,8 @@ Configurations
|
||||
There are noticeable delays in receiving the button events,
|
||||
especially when the button is released. But if you do not press the
|
||||
buttons too quickly all events are processed. This, I suspect, is a
|
||||
consequence of the strong glitch filtering that is enbled in the pin
|
||||
configuration. Snappier response my be obtainble with filtering off
|
||||
consequence of the strong glitch filtering that is enabled in the pin
|
||||
configuration. Snappier response my be obtainable with filtering off
|
||||
if desired.
|
||||
|
||||
5. This configuration has been used for testing the SDMMC driver with
|
||||
|
||||
+9
-8
@@ -70,8 +70,8 @@
|
||||
* Name: arp_arpin
|
||||
*
|
||||
* Description:
|
||||
* This function should be called by the Ethernet device driver when an ARP
|
||||
* packet has been received. The function will act differently
|
||||
* This function should be called by the Ethernet device driver when an
|
||||
* ARP packet has been received. The function will act differently
|
||||
* depending on the ARP packet type: if it is a reply for a request
|
||||
* that we previously sent out, the ARP cache will be filled in with
|
||||
* the values from the ARP reply. If the incoming ARP packet is an ARP
|
||||
@@ -82,10 +82,11 @@
|
||||
* Ethernet header is present in the d_buf buffer and that the length of
|
||||
* the packet is set in the d_len field.
|
||||
*
|
||||
* When the function returns, the value of the field d_len indicates whether
|
||||
* the device driver should send out the ARP reply packet or not. If d_len
|
||||
* is zero, no packet should be sent; If d_len is non-zero, it contains the
|
||||
* length of the outbound packet that is present in the d_buf buffer.
|
||||
* When the function returns, the value of the field d_len indicates
|
||||
* whether the device driver should send out the ARP reply packet or not.
|
||||
* If d_len is zero, no packet should be sent; If d_len is non-zero, it
|
||||
* contains the length of the outbound packet that is present in the
|
||||
* d_buf buffer.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@@ -107,7 +108,7 @@ void arp_arpin(FAR struct net_driver_s *dev)
|
||||
switch (arp->ah_opcode)
|
||||
{
|
||||
case HTONS(ARP_REQUEST):
|
||||
ninfo("ARP request for IP %04lx\n", (long)ipaddr);
|
||||
ninfo("ARP request for IP %04lx\n", (unsigned long)ipaddr);
|
||||
|
||||
/* ARP request. If it asked for our address, we send out a reply. */
|
||||
|
||||
@@ -139,7 +140,7 @@ void arp_arpin(FAR struct net_driver_s *dev)
|
||||
break;
|
||||
|
||||
case HTONS(ARP_REPLY):
|
||||
ninfo("ARP reply for IP %04lx\n", (long)ipaddr);
|
||||
ninfo("ARP reply for IP %04lx\n", (unsigned long)ipaddr);
|
||||
|
||||
/* ARP reply. We insert or update the ARP table if it was meant
|
||||
* for us.
|
||||
|
||||
Reference in New Issue
Block a user