From f8731df8137c569696cddec635ce82f178f22bbe Mon Sep 17 00:00:00 2001 From: patacongo Date: Sat, 10 Dec 2011 15:14:29 +0000 Subject: Add Ethernet interrupt configuration and handling git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4157 42af7a65-404d-4744-a932-0658087f49c3 --- nuttx/arch/arm/src/stm32/chip/stm32_eth.h | 57 +++++-------- nuttx/arch/arm/src/stm32/stm32_eth.c | 134 +++++++++++++++++++++++++++--- 2 files changed, 144 insertions(+), 47 deletions(-) (limited to 'nuttx/arch/arm/src/stm32') diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_eth.h b/nuttx/arch/arm/src/stm32/chip/stm32_eth.h index b58c9c87f..991695a09 100644 --- a/nuttx/arch/arm/src/stm32/chip/stm32_eth.h +++ b/nuttx/arch/arm/src/stm32/chip/stm32_eth.h @@ -549,23 +549,28 @@ /* Ethernet DMA receive descriptor list address register (32-bit address) */ /* Ethernet DMA transmit descriptor list address register (32-bit address) */ -/* Ethernet DMA status register */ - -#define ETH_DMASR_TS (1 << 0) /* Bit 0: Transmit status */ -#define ETH_DMASR_TPSS (1 << 1) /* Bit 1: Transmit process stopped status */ -#define ETH_DMASR_TBUS (1 << 2) /* Bit 2: Transmit buffer unavailable status */ -#define ETH_DMASR_TJTS (1 << 3) /* Bit 3: Transmit jabber timeout status */ -#define ETH_DMASR_ROS (1 << 4) /* Bit 4: Receive overflow status */ -#define ETH_DMASR_TUS (1 << 5) /* Bit 5: Transmit underflow status */ -#define ETH_DMASR_RS (1 << 6) /* Bit 6: Receive status */ -#define ETH_DMASR_RBUS (1 << 7) /* Bit 7: Receive buffer unavailable status */ -#define ETH_DMASR_RPSS (1 << 8) /* Bit 8: Receive process stopped status */ -#define ETH_DMASR_RWTS (1 << 9) /* Bit 9: Receive watchdog timeout status */ -#define ETH_DMASR_ETS (1 << 10) /* Bit 10: Early transmit status */ -#define ETH_DMASR_FBES (1 << 13) /* Bit 13: Fatal bus error status */ -#define ETH_DMASR_ERS (1 << 14) /* Bit 14: Early receive status */ -#define ETH_DMASR_AIS (1 << 15) /* Bit 15: Abnormal interrupt summary */ -#define ETH_DMASR_NIS (1 << 16) /* Bit 16: Normal interrupt summary */ +/* Interrupt bit definitions common between the DMA status register (DMASR) and + * the DMA interrupt enable register (DMAIER). + */ + +#define ETH_DMAINT_TI (1 << 0) /* Bit 0: Transmit interrupt */ +#define ETH_DMAINT_TPSI (1 << 1) /* Bit 1: Transmit process stopped interrupt */ +#define ETH_DMAINT_TBUI (1 << 2) /* Bit 2: Transmit buffer unavailable interrupt */ +#define ETH_DMAINT_TJTI (1 << 3) /* Bit 3: Transmit jabber timeout interrupt */ +#define ETH_DMAINT_ROI (1 << 4) /* Bit 4: Overflow interrupt */ +#define ETH_DMAINT_TUI (1 << 5) /* Bit 5: Underflow interrupt */ +#define ETH_DMAINT_RI (1 << 6) /* Bit 6: Receive interrupt */ +#define ETH_DMAINT_RBUI (1 << 7) /* Bit 7: Receive buffer unavailable interrupt */ +#define ETH_DMAINT_RPSI (1 << 8) /* Bit 8: Receive process stopped interrupt */ +#define ETH_DMAINT_RWTI (1 << 9) /* Bit 9: Receive watchdog timeout interrupt */ +#define ETH_DMAINT_ETI (1 << 10) /* Bit 10: Early transmit interrupt */ +#define ETH_DMAINT_FBEI (1 << 13) /* Bit 13: Fatal bus error interrupt */ +#define ETH_DMAINT_ERI (1 << 14) /* Bit 14: Early receive interrupt */ +#define ETH_DMAINT_AIS (1 << 15) /* Bit 15: Abnormal interrupt summary */ +#define ETH_DMAINT_NIS (1 << 16) /* Bit 16: Normal interrupt summary */ + +/* Ethernet DMA status register (in addition to the interrupt bits above */ + #define ETH_DMASR_RPS_SHIFT (17) /* Bits 17-19: Receive process state */ #define ETH_DMASR_RPS_MASK (7 << ETH_DMASR_RPS_SHIFT) # define ETH_DMASR_RPS_STOPPED (0 << ETH_DMASR_RPS_SHIFT) /* 000: Stopped: Reset or Stop Receive Command issued */ @@ -620,24 +625,6 @@ #define ETH_DMAOMR_RSF (1 << 25) /* Bit 25: Receive store and forward */ #define ETH_DMAOMR_DTCEFD (1 << 26) /* Bit 26: Dropping of TCP/IP checksum error frames disable */ -/* Ethernet DMA interrupt enable register */ - -#define ETH_DMAIER_TIE (1 << 0) /* Bit 0: Transmit interrupt enable */ -#define ETH_DMAIER_TPSIE (1 << 1) /* Bit 1: Transmit process stopped interrupt enable */ -#define ETH_DMAIER_TBUIE (1 << 2) /* Bit 2: Transmit buffer unavailable interrupt enable */ -#define ETH_DMAIER_TJTIE (1 << 3) /* Bit 3: Transmit jabber timeout interrupt enable */ -#define ETH_DMAIER_ROIE (1 << 4) /* Bit 4: Overflow interrupt enable */ -#define ETH_DMAIER_TUIE (1 << 5) /* Bit 5: Underflow interrupt enable */ -#define ETH_DMAIER_RIE (1 << 6) /* Bit 6: Receive interrupt enable */ -#define ETH_DMAIER_RBUIE (1 << 7) /* Bit 7: Receive buffer unavailable interrupt enable */ -#define ETH_DMAIER_RPSIE (1 << 8) /* Bit 8: Receive process stopped interrupt enable */ -#define ETH_DMAIER_RWTIE (1 << 9) /* Bit 9: Receive watchdog timeout interrupt enable */ -#define ETH_DMAIER_ETIE (1 << 10) /* Bit 10: Early transmit interrupt enable */ -#define ETH_DMAIER_FBEIE (1 << 13) /* Bit 13: Fatal bus error interrupt enable */ -#define ETH_DMAIER_ERIE (1 << 14) /* Bit 14: Early receive interrupt enable */ -#define ETH_DMAIER_AISE (1 << 15) /* Bit 15: Abnormal interrupt summary enable */ -#define ETH_DMAIER_NISE (1 << 16) /* Bit 16: Normal interrupt summary enable */ - /* Ethernet DMA missed frame and buffer overflow counter register */ #define ETH_DMAMFBOC_MFC_SHIFT (0) /* Bits 0-15: Missed frames by the controller */ diff --git a/nuttx/arch/arm/src/stm32/stm32_eth.c b/nuttx/arch/arm/src/stm32/stm32_eth.c index 05798b6b8..d4c833f40 100755 --- a/nuttx/arch/arm/src/stm32/stm32_eth.c +++ b/nuttx/arch/arm/src/stm32/stm32_eth.c @@ -428,6 +428,29 @@ ETH_DMABMR_RDP(32) | ETH_DMABMR_USP | ETH_DMABMR_AAB) #endif +/* Interrupt bit sets *******************************************************/ +/* All interrupts in the normal and abnormal interrupt summary */ + +#define ETH_DMAINT_NORMAL \ + (ETH_DMAINT_TI | ETH_DMAINT_TBUI |ETH_DMAINT_RI | ETH_DMAINT_ERI) + +#define ETH_DMAINT_ABNORMAL \ + (ETH_DMAINT_TPSI | ETH_DMAINT_TJTI | ETH_DMAINT_ROI | ETH_DMAINT_TUI | \ + ETH_DMAINT_RBUI | ETH_DMAINT_RPSI | ETH_DMAINT_RWTI | ETH_DMAINT_ETI | \ + ETH_DMAINT_FBEI) + +/* Normal receive, transmit, error interrupt enable bit sets */ + +#define ETH_DMAINT_RECV_ENABLE (ETH_DMAINT_NIS | ETH_DMAINT_RI) +#define ETH_DMAINT_XMIT_ENABLE (ETH_DMAINT_NIS | ETH_DMAINT_TI) +#define ETH_DMAINT_XMIT_DISABLE (ETH_DMAINT_TI) + +#ifdef CONFIG_DEBUG_NET +# define ETH_DMAINT_ERROR_ENABLE (ETH_DMAINT_AIS | ETH_DMAINT_ABNORMAL) +#else +# define ETH_DMAINT_ERROR_ENABLE (0) +#endif + /* Helpers ******************************************************************/ /* This is a helper pointer for accessing the contents of the Ethernet * header @@ -531,6 +554,8 @@ static int stm32_ethconfig(FAR struct stm32_ethmac_s *priv); static int stm32_transmit(FAR struct stm32_ethmac_s *priv) { + uint32_t regval; + /* Verify that the hardware is ready to send another packet. If we get * here, then we are committed to sending a packet; Higher level logic * must have assured that there is no transmission in progress. @@ -542,6 +567,10 @@ static int stm32_transmit(FAR struct stm32_ethmac_s *priv) /* Enable Tx interrupts */ + regval = getreg32(STM32_ETH_DMAIER); + regval |= ETH_DMAINT_XMIT_ENABLE; + putreg32(regval, STM32_ETH_DMAIER); + /* Setup the TX timeout watchdog (perhaps restarting the timer) */ (void)wd_start(priv->txtimeout, STM32_TXTIMEOUT, stm32_txtimeout, 1, (uint32_t)priv); @@ -683,14 +712,20 @@ static void stm32_receive(FAR struct stm32_ethmac_s *priv) static void stm32_txdone(FAR struct stm32_ethmac_s *priv) { + uint32_t regval; + /* Check for errors and update statistics */ - /* If no further xmits are pending, then cancel the TX timeout and - * disable further Tx interrupts. - */ + /* If no further xmits are pending, then cancel the TX timeout */ wd_cancel(priv->txtimeout); + /* And disable further Tx interrupts. */ + + regval = getreg32(STM32_ETH_DMAIER); + regval &= ~ETH_DMAINT_XMIT_DISABLE; + putreg32(regval, STM32_ETH_DMAIER); + /* Then poll uIP for new XMIT data */ (void)uip_poll(&priv->dev, stm32_uiptxpoll); @@ -716,22 +751,79 @@ static void stm32_txdone(FAR struct stm32_ethmac_s *priv) static int stm32_interrupt(int irq, FAR void *context) { register FAR struct stm32_ethmac_s *priv = &g_stm32ethmac[0]; + uint32_t dmasr; - /* Get and clear interrupt status bits */ + /* Get the DMA interrupt status bits (no MAC interrupts are expected) */ - /* Handle interrupts according to status bit settings */ + dmasr = getreg32(STM32_ETH_DMASR); - /* Check if we received an incoming packet, if so, call stm32_receive() */ + /* Mask only enabled interrupts. This depends on the fact that the interrupt + * related bits (0-16) correspond in these two registers. + */ - stm32_receive(priv); + dmasr &= ~getreg32(STM32_ETH_DMAIER); - /* Check if a packet transmission just completed. If so, call stm32_txdone. - * This may disable further Tx interrupts if there are no pending - * tansmissions. - */ + /* Check if there are pending "normal" interrupts */ - stm32_txdone(priv); + if ((dmasr & ETH_DMAINT_NIS) != 0) + { + /* Yes.. Check if we received an incoming packet, if so, call + * stm32_receive() + */ + if ((dmasr & ETH_DMAINT_RI) != 0) + { + /* Clear the pending receive interrupt */ + + putreg32(ETH_DMAINT_RI, STM32_ETH_DMASR); + + /* Handle the received package */ + + stm32_receive(priv); + } + + /* Check if a packet transmission just completed. If so, call + * stm32_txdone(). This may disable further Tx interrupts if there + * are no pending tansmissions. + */ + + if ((dmasr & ETH_DMAINT_TI) != 0) + { + /* Clear the pending receive interrupt */ + + putreg32(ETH_DMAINT_TI, STM32_ETH_DMASR); + + /* Check if there are pending transmissions */ + + stm32_txdone(priv); + } + + /* Clear the pending normal summary interrupt */ + + putreg32(ETH_DMAINT_NIS, STM32_ETH_DMASR); + } + + /* Handle error interrupt only if CONFIG_DEBUG_NET is eanbled */ + +#ifdef CONFIG_DEBUG_NET + + /* Check if there are pending "anormal" interrupts */ + + if ((dmasr & ETH_DMAINT_AIS) != 0) + { + /* Just let the user know what happened */ + + nlldbg("Abormal event(s): %08x\n", dmasr); + + /* Clear all pending abnormal events */ + + putreg32(ETH_DMAINT_ABNORMAL, STM32_ETH_DMASR); + + /* Clear the pending normal summary interrupt */ + + putreg32(ETH_DMAINT_NIS, STM32_ETH_DMASR); + } +#endif return OK; } @@ -1498,6 +1590,24 @@ static int stm32_macconfig(FAR struct stm32_ethmac_s *priv) regval |= DMABMR_SET_MASK; putreg32(regval, STM32_ETH_DMABMR); + /* Enable Ethernet DMA interrupts. + * + * The STM32 hardware supports two interrupts: (1) one dedicated to normal + * Ethernet operations and the other, used only for the Ethernet wakeup + * event. The wake-up interrupt is not used by this driver. + * + * The first Ethernet vector is reserved for interrupts generated by the + * MAC and the DMA. The MAC provides PMT and time stamp trigger interrupts, + * neither of which are used by this driver. + * + * Ethernet DMA supports two classes of interrupts: Normal interrupt + * summary (NIS) and Abnormal interrupt summary (AIS) with a variety + * individual normal and abnormal interrupting events. Here only + * the normal receive event is enabled (unless DEBUG is enabled). Transmit + * events will only be enabled when a transmit interrupt is expected. + */ + + putreg32((ETH_DMAINT_RECV_ENABLE | ETH_DMAINT_ERROR_ENABLE), STM32_ETH_DMAIER); return OK; } -- cgit v1.2.3