From 64fb9f608a9d818712657b174c1952107d3d9ae0 Mon Sep 17 00:00:00 2001 From: patacongo Date: Wed, 24 Nov 2010 01:47:22 +0000 Subject: Misc receive improvements git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3125 42af7a65-404d-4744-a932-0658087f49c3 --- nuttx/arch/arm/src/lpc17xx/lpc17_ethernet.c | 130 +++++++++++++++------------- 1 file changed, 68 insertions(+), 62 deletions(-) (limited to 'nuttx/arch/arm/src/lpc17xx') diff --git a/nuttx/arch/arm/src/lpc17xx/lpc17_ethernet.c b/nuttx/arch/arm/src/lpc17xx/lpc17_ethernet.c index 2e630cb2b..c9c3bfb54 100644 --- a/nuttx/arch/arm/src/lpc17xx/lpc17_ethernet.c +++ b/nuttx/arch/arm/src/lpc17xx/lpc17_ethernet.c @@ -896,16 +896,19 @@ static void lpc17_rxdone(struct lpc17_driver_s *priv) EMAC_STAT(priv, rx_packets); - /* Get the Rx status and packet length */ + /* Get the Rx status and packet length (-4+1) */ rxstat = (uint32_t*)(LPC17_RXSTAT_BASE + (considx << 3)); - pktlen = (*rxstat & RXSTAT_INFO_RXSIZE_MASK) + 1; + pktlen = (*rxstat & RXSTAT_INFO_RXSIZE_MASK) - 3; - /* Check for errors */ + /* Check for errors. NOTE: The DMA engine reports bogus length errors, + * making this a pretty useless check. + */ if ((*rxstat & RXSTAT_INFO_ERROR) != 0) { - nlldbg("Error. rxstat: %08x\n", *rxstat); + nlldbg("Error. considx: %08x prodidx: %08x rxstat: %08x\n", + considx, prodidx, *rxstat); EMAC_STAT(priv, rx_pkterr); } @@ -915,20 +918,23 @@ static void lpc17_rxdone(struct lpc17_driver_s *priv) * imply that the packet is too big. */ - else if (pktlen > CONFIG_NET_BUFSIZE+2) + /* else */ if (pktlen > CONFIG_NET_BUFSIZE+2) { - nlldbg("Too big. pktlen: %d rxstat: %08x\n", pktlen, *rxstat); + nlldbg("Too big. considx: %08x prodidx: %08x pktlen: %d rxstat: %08x\n", + considx, prodidx, pktlen, *rxstat); EMAC_STAT(priv, rx_pktsize); } else if ((*rxstat & RXSTAT_INFO_LASTFLAG) == 0) { - nlldbg("Fragment. rxstat: %08x\n", pktlen, *rxstat); + nlldbg("Fragment. considx: %08x prodidx: %08x pktlen: %d rxstat: %08x\n", + considx, prodidx, pktlen, *rxstat); EMAC_STAT(priv, rx_fragment); fragment = true; } else if (fragment) { - nlldbg("Last fragment. rxstat: %08x\n", pktlen, *rxstat); + nlldbg("Last fragment. considx: %08x prodidx: %08x pktlen: %d rxstat: %08x\n", + considx, prodidx, pktlen, *rxstat); EMAC_STAT(priv, rx_fragment); fragment = false; } @@ -1115,13 +1121,16 @@ static int lpc17_interrupt(int irq, void *context) status = lpc17_getreg(LPC17_ETH_INTST); if (status != 0) { + /* Clear all pending interrupts */ + + lpc17_putreg(status, LPC17_ETH_INTCLR); + /* Handle each pending interrupt **************************************/ /* Check for Wake-Up on Lan *******************************************/ #ifdef CONFIG_NET_WOL if ((status & ETH_INT_WKUP) != 0) { - lpc17_putreg(ETH_INT_WKUP, LPC17_ETH_INTCLR); EMAC_STAT(priv, wol); # warning "Missing logic" } @@ -1142,13 +1151,13 @@ static int lpc17_interrupt(int irq, void *context) { if ((status & ETH_INT_RXOVR) != 0) { - lpc17_putreg(ETH_INT_RXOVR, LPC17_ETH_INTCLR); - EMAC_STAT(priv, rx_ovrerrors); + nlldbg("RX Overrun. status: %08x\n", status); + EMAC_STAT(priv, rx_ovrerrors); } if ((status & ETH_INT_TXUNR) != 0) { - lpc17_putreg(ETH_INT_TXUNR, LPC17_ETH_INTCLR); + nlldbg("TX Underrun. status: %08x\n", status); EMAC_STAT(priv, tx_underrun); } @@ -1160,82 +1169,79 @@ static int lpc17_interrupt(int irq, void *context) { /* Check for receive events ***************************************/ /* RX ERROR -- Triggered on receive errors: AlignmentError, - * RangeError, LengthError, SymbolError, CRCError or - * NoDescriptor or Overrun. + * RangeError, LengthError, SymbolError, CRCError or NoDescriptor + * or Overrun. NOTE: (1) We will still need to call lpc17_rxdone + * on RX errors to bump the considx over the bad packet. (2) The + * DMA engine reports bogus length errors, making this a pretty + * useless check anyway. */ if ((status & ETH_INT_RXERR) != 0) { - lpc17_putreg(ETH_INT_RXERR, LPC17_ETH_INTCLR); + nlldbg("RX Error. status: %08x\n", status); EMAC_STAT(priv, rx_errors); } - else - { - /* RX FINISHED -- Triggered when all receive descriptors have - * been processed i.e. on the transition to the situation - * where ProduceIndex == ConsumeIndex. - */ - if ((status & ETH_INT_RXFIN) != 0) - { - lpc17_putreg(ETH_INT_RXFIN, LPC17_ETH_INTCLR); - EMAC_STAT(priv, rx_finished); - DEBUGASSERT(lpc17_getreg(LPC17_ETH_RXPRODIDX) == lpc17_getreg(LPC17_ETH_RXCONSIDX)); - } + /* RX FINISHED -- Triggered when all receive descriptors have + * been processed i.e. on the transition to the situation + * where ProduceIndex == ConsumeIndex. + */ - /* RX DONE -- Triggered when a receive descriptor has been - * processed while the Interrupt bit in the Control field of - * the descriptor was set. - */ + if ((status & ETH_INT_RXFIN) != 0) + { + EMAC_STAT(priv, rx_finished); + DEBUGASSERT(lpc17_getreg(LPC17_ETH_RXPRODIDX) == lpc17_getreg(LPC17_ETH_RXCONSIDX)); + } - if ((status & ETH_INT_RXDONE) != 0) - { - lpc17_putreg(ETH_INT_RXDONE, LPC17_ETH_INTCLR); - EMAC_STAT(priv, rx_done); + /* RX DONE -- Triggered when a receive descriptor has been + * processed while the Interrupt bit in the Control field of + * the descriptor was set. + */ - /* We have received at least one new incoming packet. */ + if ((status & ETH_INT_RXDONE) != 0) + { + EMAC_STAT(priv, rx_done); - lpc17_rxdone(priv); - } - } + /* We have received at least one new incoming packet. */ + lpc17_rxdone(priv); + } + /* Check for Tx events ********************************************/ /* TX ERROR -- Triggered on transmit errors: LateCollision, * ExcessiveCollision and ExcessiveDefer, NoDescriptor or Underrun. + * NOTE: We will still need to call lpc17_txdone() in order to + * clean up after the failed transmit. */ if ((status & ETH_INT_TXERR) != 0) { - lpc17_putreg(ETH_INT_TXERR, LPC17_ETH_INTCLR); + nlldbg("TX Error. status: %08x\n", status); EMAC_STAT(priv, tx_errors); } - else - { - /* TX FINISHED -- Triggered when all transmit descriptors have - * been processed i.e. on the transition to the situation - * where ProduceIndex == ConsumeIndex. - */ - if ((status & ETH_INT_TXFIN) != 0) - { - lpc17_putreg(ETH_INT_TXFIN, LPC17_ETH_INTCLR); - EMAC_STAT(priv, tx_finished); - } + /* TX FINISHED -- Triggered when all transmit descriptors have + * been processed i.e. on the transition to the situation + * where ProduceIndex == ConsumeIndex. + */ - /* TX DONE -- Triggered when a descriptor has been transmitted - * while the Interrupt bit in the Control field of the - * descriptor was set. - */ + if ((status & ETH_INT_TXFIN) != 0) + { + EMAC_STAT(priv, tx_finished); + } - if ((status & ETH_INT_TXDONE) != 0) - { - lpc17_putreg(ETH_INT_TXDONE, LPC17_ETH_INTCLR); - EMAC_STAT(priv, tx_done); + /* TX DONE -- Triggered when a descriptor has been transmitted + * while the Interrupt bit in the Control field of the + * descriptor was set. + */ + + if ((status & ETH_INT_TXDONE) != 0) + { + EMAC_STAT(priv, tx_done); - /* A packet transmission just completed */ + /* A packet transmission just completed */ - lpc17_txdone(priv); - } + lpc17_txdone(priv); } } } -- cgit v1.2.3