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:
parent
eab386aeda
commit
6154943d4b
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user