From ba88a8aa883ce46777479a900d8c3a58b06fad50 Mon Sep 17 00:00:00 2001 From: patacongo Date: Sat, 13 Nov 2010 19:31:01 +0000 Subject: [PATCH] Add ethernet interrupt handler git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3106 42af7a65-404d-4744-a932-0658087f49c3 --- arch/arm/src/lm3s/lm3s_ethernet.c | 6 +- arch/arm/src/lpc17xx/lpc17_ethernet.c | 122 +++++++++++++++++++++++--- arch/arm/src/lpc17xx/lpc17_ethernet.h | 2 +- 3 files changed, 113 insertions(+), 17 deletions(-) diff --git a/arch/arm/src/lm3s/lm3s_ethernet.c b/arch/arm/src/lm3s/lm3s_ethernet.c index b66e8be422..af78660e9b 100644 --- a/arch/arm/src/lm3s/lm3s_ethernet.c +++ b/arch/arm/src/lm3s/lm3s_ethernet.c @@ -160,14 +160,14 @@ /* EMAC statistics (debug only) */ #if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_NET) -struct ez80mac_statistics_s +struct lm3s_statistics_s { uint32_t rx_int; /* Number of Rx interrupts received */ uint32_t rx_packets; /* Number of packets received (sum of the following): */ uint32_t rx_ip; /* Number of Rx IP packets received */ uint32_t rx_arp; /* Number of Rx ARP packets received */ uint32_t rx_dropped; /* Number of dropped, unsupported Rx packets */ - uint32_t rx_pktsize; /* Number of dropped, too small or too bigr */ + uint32_t rx_pktsize; /* Number of dropped, too small or too big */ uint32_t rx_errors; /* Number of Rx errors (reception error) */ uint32_t rx_ovrerrors; /* Number of Rx FIFO overrun errors */ uint32_t tx_int; /* Number of Tx interrupts received */ @@ -200,7 +200,7 @@ struct lm3s_driver_s WDOG_ID ld_txtimeout; /* TX timeout timer */ #if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_NET) - struct ez80mac_statistics_s ld_stat; + struct lm3s_statistics_s ld_stat; #endif /* This holds the information visible to uIP/NuttX */ diff --git a/arch/arm/src/lpc17xx/lpc17_ethernet.c b/arch/arm/src/lpc17xx/lpc17_ethernet.c index a1ee40c4a7..b20e811fd0 100644 --- a/arch/arm/src/lpc17xx/lpc17_ethernet.c +++ b/arch/arm/src/lpc17xx/lpc17_ethernet.c @@ -289,6 +289,36 @@ * Private Types ****************************************************************************/ +/* EMAC statistics (debug only) */ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_NET) +struct lpc17_statistics_s +{ +#if ENABLE_WOL + uint32_t wol; /* Wake-up interrupts */ +#endif + uint32_t rx_finished; /* Rx finished interrupts */ + uint32_t rx_done; /* Rx done interrupts */ + uint32_t rx_ovrerrors; /* Number of Rx overrun error interrupts */ + uint32_t rx_errors; /* Number of Rx error interrupts (OR of other errors) */ + uint32_t rx_packets; /* Number of packets received (sum of the following): */ + uint32_t rx_ip; /* Number of Rx IP packets received */ + uint32_t rx_arp; /* Number of Rx ARP packets received */ + uint32_t rx_dropped; /* Number of dropped, unsupported Rx packets */ + uint32_t rx_pktsize; /* Number of dropped, too small or too big */ + + uint32_t tx_packets; /* Number of Tx packets queued */ + uint32_t tx_finished; /* Tx finished interrupts */ + uint32_t tx_done; /* Tx done interrupts */ + uint32_t tx_underrun; /* Number of Tx underrun error interrupts */ + uint32_t tx_errors; /* Number of Tx error inerrupts (OR of other errors) */ + uint32_t tx_timeouts; /* Number of Tx timeout errors */ +}; +# define EMAC_STAT(priv,name) priv->lp_stat.name++ +#else +# define EMAC_STAT(priv,name) +#endif + /* The lpc17_driver_s encapsulates all state information for a single hardware * interface */ @@ -311,6 +341,10 @@ struct lpc17_driver_s #endif WDOG_ID lp_txpoll; /* TX poll timer */ WDOG_ID lp_txtimeout; /* TX timeout timer */ + +#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_NET) + struct lpc17_statistics_s lp_stat; +#endif /* This holds the information visible to uIP/NuttX */ @@ -742,24 +776,86 @@ static void lpc17_txdone(FAR struct lpc17_driver_s *priv) static int lpc17_interrupt(int irq, FAR void *context) { register FAR struct lpc17_driver_s *priv = &g_ethdrvr[0]; + uint32_t status; - /* Disable Ethernet interrupts */ + /* Get the interrupt status (zero means no interrupts pending). */ - /* Get and clear interrupt status bits */ + status = lpc17_getreg(LPC17_ETH_INTST); + if (status != 0) + { + /* Handle each pending interrupt */ + /* Check for receive errors */ - /* Handle interrupts according to status bit settings */ + if ((status & ETH_INT_RXOVR) != 0) + { + lpc17_putreg(ETH_INT_RXOVR, LPC17_ETH_INTCLR); + EMAC_STAT(priv, rx_ovrerrors); + } - /* Check if we received an incoming packet, if so, call lpc17_receive() */ + if ((status & ETH_INT_RXERR) != 0) + { + lpc17_putreg(ETH_INT_RXERR, LPC17_ETH_INTCLR); + EMAC_STAT(priv, rx_errors); + } - lpc17_receive(priv); + /* Check if we received an incoming packet, if so, call lpc17_receive() */ - /* Check is a packet transmission just completed. If so, call lpc17_txdone */ + 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)); + } - lpc17_txdone(priv); + if ((status & ETH_INT_RXDONE) != 0) + { + lpc17_putreg(ETH_INT_RXDONE, LPC17_ETH_INTCLR); + EMAC_STAT(priv, rx_done); + lpc17_receive(priv); + } - /* Enable Ethernet interrupts (perhaps excluding the TX done interrupt if - * there are no pending transmissions. - */ + /* Check for Tx errors */ + + if ((status & ETH_INT_TXUNR) != 0) + { + lpc17_putreg(ETH_INT_TXUNR, LPC17_ETH_INTCLR); + EMAC_STAT(priv, tx_underrun); + } + + if ((status & ETH_INT_TXERR) != 0) + { + lpc17_putreg(ETH_INT_TXERR, LPC17_ETH_INTCLR); + EMAC_STAT(priv, tx_errors); + } + + /* Check is a packet transmission just completed. If so, call lpc17_txdone */ + + if ((status & ETH_INT_TXFIN) != 0) + { + lpc17_putreg(ETH_INT_TXFIN, LPC17_ETH_INTCLR); + EMAC_STAT(priv, tx_finished); + } + + if ((status & ETH_INT_TXDONE) != 0) + { + lpc17_putreg(ETH_INT_TXDONE, LPC17_ETH_INTCLR); + EMAC_STAT(priv, tx_done); + lpc17_txdone(priv); + } + + /* Check for Wake-Up on Lan */ + +#if CONFIG_NET_WOL + if ((status & ETH_INT_WKUP) != 0) + { + lpc17_putreg(ETH_INT_WKUP, LPC17_ETH_INTCLR); + INTCLEAR = EMAC_INT_WOL; + EMAC_STAT(priv, wol); +# warning "Missing logic" + } +#endif + + } return OK; } @@ -857,7 +953,7 @@ static int lpc17_ifup(struct uip_driver_s *dev) ndbg("Bringing up: %d.%d.%d.%d\n", dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff, - (dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24 ); + (dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24); /* Reset the Ethernet controller (again) */ @@ -954,7 +1050,7 @@ static int lpc17_ifup(struct uip_driver_s *dev) lpc17_putreg((ETH_INT_RXOVR | ETH_INT_RXERR | ETH_INT_RXFIN | ETH_INT_RXDONE | ETH_INT_TXUNR | ETH_INT_TXERR | ETH_INT_TXFIN | ETH_INT_TXDONE), - LPC17_ETH_INTEN); + LPC17_ETH_INTEN); #endif /* Set and activate a timer process */ @@ -1620,7 +1716,7 @@ static inline void lpc17_txdescinit(struct lpc17_driver_s *priv) { *txdesc++ = pktaddr; *txdesc++ = (TXDESC_CONTROL_INT | (LPC17_MAXPACKET_SIZE - 1)); - pktaddr += LPC17_MAXPACKET_SIZE; + pktaddr += LPC17_MAXPACKET_SIZE; } /* Initialize Tx status */ diff --git a/arch/arm/src/lpc17xx/lpc17_ethernet.h b/arch/arm/src/lpc17xx/lpc17_ethernet.h index 61af1f793e..3afed26cb6 100755 --- a/arch/arm/src/lpc17xx/lpc17_ethernet.h +++ b/arch/arm/src/lpc17xx/lpc17_ethernet.h @@ -459,7 +459,7 @@ #define ETH_RXFLCTRL_PERFEN (1 << 5) /* Bit 5: Accept perfect dest match */ /* Bits 6-11: Reserved */ #define ETH_RXFLCTRL_MPKTEN (1 << 12) /* Bit 12: Magic pkt filter WoL int */ -#define ETH_RXFLCTRL_RXFILEN (1 << 13) /* Bit 13: Perfect math WoL interrupt */ +#define ETH_RXFLCTRL_RXFILEN (1 << 13) /* Bit 13: Perfect match WoL interrupt */ /* Bits 14-31: Reserved */ /* Receive filter WoL status register (RXFLWOLST) AND * Receive filter WoL clear register (RXFLWOLCLR)