Add Ethernet interrupt configuration and handling

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4157 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2011-12-10 15:14:29 +00:00
parent 3d423084f5
commit 4e4744da73
2 changed files with 144 additions and 47 deletions

View File

@ -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 */
/* 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_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 */
#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 */

View File

@ -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() */
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.
/* Mask only enabled interrupts. This depends on the fact that the interrupt
* related bits (0-16) correspond in these two registers.
*/
stm32_txdone(priv);
dmasr &= ~getreg32(STM32_ETH_DMAIER);
/* Check if there are pending "normal" interrupts */
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;
}