Ejemplo n.º 1
0
/**
 * \brief GMAC Interrupt handler.
 *
 * \param p_gmac_dev   Pointer to GMAC device instance.
 */
void gmac_handler(gmac_device_t* p_gmac_dev)
{
	Gmac *p_hw = p_gmac_dev->p_hw;

	gmac_tx_descriptor_t *p_tx_td;
	gmac_dev_tx_cb_t *p_tx_cb;
	volatile uint32_t ul_isr;
	volatile uint32_t ul_rsr;
	volatile uint32_t ul_tsr;
	uint32_t ul_rx_status_flag;
	uint32_t ul_tx_status_flag;

	ul_isr = gmac_get_interrupt_status(p_hw);
	ul_rsr = gmac_get_rx_status(p_hw);
	ul_tsr = gmac_get_tx_status(p_hw);

	ul_isr &= ~(gmac_get_interrupt_mask(p_hw) | 0xF8030300);

	/* RX packet */
	if ((ul_isr & GMAC_ISR_RCOMP) || (ul_rsr & GMAC_RSR_REC)) {
		ul_rx_status_flag = GMAC_RSR_REC;

		/* Check OVR */
		if (ul_rsr & GMAC_RSR_RXOVR) {
			ul_rx_status_flag |= GMAC_RSR_RXOVR;
		}
		/* Check BNA */
		if (ul_rsr & GMAC_RSR_BNA) {
			ul_rx_status_flag |= GMAC_RSR_BNA;
		}
		/* Clear status */
		gmac_clear_rx_status(p_hw, ul_rx_status_flag);

		/* Invoke callbacks */
		if (p_gmac_dev->func_rx_cb) {
			p_gmac_dev->func_rx_cb(ul_rx_status_flag);
		}
	}

	/* TX packet */
	if ((ul_isr & GMAC_ISR_TCOMP) || (ul_tsr & GMAC_TSR_TXCOMP)) {

		ul_tx_status_flag = GMAC_TSR_TXCOMP;

		/* A frame transmitted */

		/* Check RLE */
		if (ul_tsr & GMAC_TSR_RLE) {
			/* Status RLE & Number of discarded buffers */
			ul_tx_status_flag = GMAC_TSR_RLE | CIRC_CNT(p_gmac_dev->us_tx_head,
					p_gmac_dev->us_tx_tail, p_gmac_dev->us_tx_list_size);
			p_tx_cb = &p_gmac_dev->func_tx_cb_list[p_gmac_dev->us_tx_tail];
			gmac_reset_tx_mem(p_gmac_dev);
			gmac_enable_transmit(p_hw, 1);
		}
		/* Check COL */
		if (ul_tsr & GMAC_TSR_COL) {
			ul_tx_status_flag |= GMAC_TSR_COL;
		}
		/* Check UND */
		if (ul_tsr & GMAC_TSR_UND) {
			ul_tx_status_flag |= GMAC_TSR_UND;
		}
		/* Clear status */
		gmac_clear_tx_status(p_hw, ul_tx_status_flag);

		if (!CIRC_EMPTY(p_gmac_dev->us_tx_head, p_gmac_dev->us_tx_tail)) {
			/* Check the buffers */
			do {
				p_tx_td = &p_gmac_dev->p_tx_dscr[p_gmac_dev->us_tx_tail];
				p_tx_cb = &p_gmac_dev->func_tx_cb_list[p_gmac_dev->us_tx_tail];
				/* Any error? Exit if buffer has not been sent yet */
				if ((p_tx_td->status.val & GMAC_TXD_USED) == 0) {
					break;
				}

				/* Notify upper layer that a packet has been sent */
				if (*p_tx_cb) {
					(*p_tx_cb) (ul_tx_status_flag);
				}

				circ_inc(&p_gmac_dev->us_tx_tail, p_gmac_dev->us_tx_list_size);
			} while (CIRC_CNT(p_gmac_dev->us_tx_head, p_gmac_dev->us_tx_tail,
							p_gmac_dev->us_tx_list_size));
		}

		if (ul_tsr & GMAC_TSR_RLE) {
			/* Notify upper layer RLE */
			if (*p_tx_cb) {
				(*p_tx_cb) (ul_tx_status_flag);
			}
		}

		/* If a wakeup has been scheduled, notify upper layer that it can
		   send other packets, and the sending will be successful. */
		if ((CIRC_SPACE(p_gmac_dev->us_tx_head, p_gmac_dev->us_tx_tail,
				p_gmac_dev->us_tx_list_size) >= p_gmac_dev->uc_wakeup_threshold)
				&& p_gmac_dev->func_wakeup_cb) {
			p_gmac_dev->func_wakeup_cb();
		}
	}
}
Ejemplo n.º 2
0
//-----------------------------------------------------------------------------
/// EMAC Interrupt handler
//-----------------------------------------------------------------------------
void EMAC_Handler(void)
{
    volatile EmacTxTDescriptor *pTxTd;
    volatile EMAC_TxCallback   *pTxCb;
    unsigned int isr;
    unsigned int rsr;
    unsigned int tsr;
    unsigned int rxStatusFlag;
    unsigned int txStatusFlag;

    //TRACE_DEBUG("EMAC_Handler\n\r");
    isr = AT91C_BASE_EMAC->EMAC_ISR & AT91C_BASE_EMAC->EMAC_IMR;
    rsr = AT91C_BASE_EMAC->EMAC_RSR;
    tsr = AT91C_BASE_EMAC->EMAC_TSR;

    // RX packet
    if ((isr & AT91C_EMAC_RCOMP) || (rsr & AT91C_EMAC_REC)) {
        rxStatusFlag = AT91C_EMAC_REC;

        // Frame received
        EmacStatistics.rx_packets++;

        // Check OVR
        if (rsr & AT91C_EMAC_OVR) {
            rxStatusFlag |= AT91C_EMAC_OVR;
            EmacStatistics.rx_ovrs++;
        }
        // Check BNA
        if (rsr & AT91C_EMAC_BNA) {
            rxStatusFlag |= AT91C_EMAC_BNA;
            EmacStatistics.rx_bnas++;
        }
        // Clear status
        AT91C_BASE_EMAC->EMAC_RSR |= rxStatusFlag;

        // Invoke callbacks
        if (rxTd.rxCb) {
            rxTd.rxCb(rxStatusFlag);
        }
    }

    // TX packet
    if ((isr & AT91C_EMAC_TCOMP) || (tsr & AT91C_EMAC_COMP)) {

        txStatusFlag = AT91C_EMAC_COMP;
        EmacStatistics.tx_comp ++;

        // A frame transmitted
        // Check RLE
        if (tsr & AT91C_EMAC_RLES) {
            txStatusFlag |= AT91C_EMAC_RLES;
            EmacStatistics.tx_errors++;
        }
        // Check COL
        if (tsr & AT91C_EMAC_COL) {
            txStatusFlag |= AT91C_EMAC_COL;
            EmacStatistics.collisions++;
        }
        // Check BEX
        if (tsr & AT91C_EMAC_BEX) {
            txStatusFlag |= AT91C_EMAC_BEX;
            EmacStatistics.tx_exausts++;
        }
        // Check UND
        if (tsr & AT91C_EMAC_UND) {
            txStatusFlag |= AT91C_EMAC_UND;
            EmacStatistics.tx_underruns++;
        }
        // Clear status
        AT91C_BASE_EMAC->EMAC_TSR |= txStatusFlag;

        // Sanity check: Tx buffers have to be scheduled
        ASSERT(!CIRC_EMPTY(&txTd),
            "-F- EMAC Tx interrupt received meanwhile no TX buffers has been scheduled\n\r");

        // Check the buffers
        while (CIRC_CNT(txTd.head, txTd.tail, TX_BUFFERS)) {
            pTxTd = txTd.td + txTd.tail;
            pTxCb = txTd.txCb + txTd.tail;

            // Exit if buffer has not been sent yet
            if ((pTxTd->status & EMAC_TX_USED_BIT) == 0) {
                break;
            }

            // Notify upper layer that packet has been sent
            if (*pTxCb) {
                (*pTxCb)(txStatusFlag);
            }

            CIRC_INC( txTd.tail, TX_BUFFERS );
        }

        // If a wakeup has been scheduled, notify upper layer that it can send
        // other packets, send will be successfull.
        if( (CIRC_SPACE(txTd.head, txTd.tail, TX_BUFFERS) >= txTd.wakeupThreshold)
         &&  txTd.wakeupCb) {
            txTd.wakeupCb();
        }
    }
}
Ejemplo n.º 3
0
//-----------------------------------------------------------------------------
/// EMAC Interrupt handler
//-----------------------------------------------------------------------------
void EMAC_Handler(void)
{
    volatile EmacTxTDescriptor *pTxTd;
    volatile EMAC_TxCallback   *pTxCb;
    volatile unsigned int isr;
    volatile unsigned int rsr;
    volatile unsigned int tsr;
    unsigned int rxStatusFlag;
    unsigned int txStatusFlag;

    //TRACE_DEBUG("EMAC_Handler\n\r");
    isr = AT91C_BASE_EMAC->EMAC_ISR;
    rsr = AT91C_BASE_EMAC->EMAC_RSR;
    tsr = AT91C_BASE_EMAC->EMAC_TSR;
    isr &= ~(AT91C_BASE_EMAC->EMAC_IMR | 0xFFC300);

    // RX packet
    if ((isr & AT91C_EMAC_RCOMP) || (rsr & AT91C_EMAC_REC)) {
        rxStatusFlag = AT91C_EMAC_REC;

        // Frame received
        EmacStatistics.rx_packets++;

        // Check OVR
        if (rsr & AT91C_EMAC_OVR) {
            rxStatusFlag |= AT91C_EMAC_OVR;
            EmacStatistics.rx_ovrs++;
        }
        // Check BNA
        if (rsr & AT91C_EMAC_BNA) {
            rxStatusFlag |= AT91C_EMAC_BNA;
            EmacStatistics.rx_bnas++;
        }
        // Clear status
        AT91C_BASE_EMAC->EMAC_RSR |= rxStatusFlag;

        // Invoke callbacks
        if (rxTd.rxCb) {
            rxTd.rxCb(rxStatusFlag);
        }
    }

    // TX packet
    if ((isr & AT91C_EMAC_TCOMP) || (tsr & AT91C_EMAC_COMP)) {

        txStatusFlag = AT91C_EMAC_COMP;
        EmacStatistics.tx_comp ++;

        // A frame transmitted
        // Check RLE
        if (tsr & AT91C_EMAC_RLES) {
            // Status RLE & Number of discarded buffers
            txStatusFlag = AT91C_EMAC_RLES
                         | CIRC_CNT(txTd.head, txTd.tail, TX_BUFFERS);
            pTxCb = txTd.txCb + txTd.tail;
            EMAC_ResetTx();
            TRACE_INFO("Tx RLE!!\n\r");
            AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_TE;
            EmacStatistics.tx_errors++;
        }
        // Check COL
        if (tsr & AT91C_EMAC_COL) {
            txStatusFlag |= AT91C_EMAC_COL;
            EmacStatistics.collisions++;
        }
        // Check BEX
        if (tsr & AT91C_EMAC_BEX) {
            txStatusFlag |= AT91C_EMAC_BEX;
            EmacStatistics.tx_exausts++;
        }
        // Check UND
        if (tsr & AT91C_EMAC_UND) {
            txStatusFlag |= AT91C_EMAC_UND;
            EmacStatistics.tx_underruns++;
        }
        // Clear status
        AT91C_BASE_EMAC->EMAC_TSR |= txStatusFlag;

        if (!CIRC_EMPTY(&txTd))
        {
            // Check the buffers
            do {
                pTxTd = txTd.td + txTd.tail;
                pTxCb = txTd.txCb + txTd.tail;
                // Any error?
                // Exit if buffer has not been sent yet
                if ((pTxTd->status & EMAC_TX_USED_BIT) == 0) {
                    break;
                }

                // Notify upper layer that a packet has been sent
                if (*pTxCb) {
                    (*pTxCb)(txStatusFlag);
                }

                CIRC_INC( txTd.tail, TX_BUFFERS );
            } while (CIRC_CNT(txTd.head, txTd.tail, TX_BUFFERS));
        }
        
        if (tsr & AT91C_EMAC_RLES) {
            // Notify upper layer RLE
            if (*pTxCb) {
                (*pTxCb)(txStatusFlag);
            }
        }
        
        // If a wakeup has been scheduled, notify upper layer that it can  
        // send other packets, send will be successfull.
        if( (CIRC_SPACE(txTd.head, txTd.tail, TX_BUFFERS) >=
                                            txTd.wakeupThreshold)
         &&  txTd.wakeupCb) {
            txTd.wakeupCb();
        }
    }

    // PAUSE Frame
    if (isr & AT91C_EMAC_PFRE) {
        TRACE_INFO("Pause!\n\r");
    }
    if (isr & AT91C_EMAC_PTZ) {
        TRACE_INFO("Pause TO!\n\r");
    }
}
Ejemplo n.º 4
0
/**
 * \brief GMAC Interrupt handler.
 *
 * \param p_gmac_dev   Pointer to GMAC device instance.
 */
void gmac_handler(gmac_device_t* p_gmac_dev, gmac_quelist_t queue_idx)
{
	Gmac *p_hw = p_gmac_dev->p_hw;

	gmac_tx_descriptor_t *p_tx_td;
	gmac_dev_tx_cb_t *p_tx_cb;
	volatile uint32_t ul_isr;
	volatile uint32_t ul_rsr;
	volatile uint32_t ul_tsr;
	uint32_t ul_rx_status_flag;
	uint32_t ul_tx_status_flag;
#ifdef FREERTOS_USED
	portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
#endif

	gmac_queue_t* p_gmac_queue = &p_gmac_dev->gmac_queue_list[queue_idx];

	if(queue_idx == GMAC_QUE_0) {
		ul_isr = gmac_get_interrupt_status(p_hw);
	} else {
		ul_isr = gmac_get_priority_interrupt_status(p_hw, queue_idx);
	}
	ul_rsr = gmac_get_rx_status(p_hw);
	ul_tsr = gmac_get_tx_status(p_hw);

	ul_isr &= ~(gmac_get_interrupt_mask(p_hw) | 0xF8030300);

	/* RX packet */
	if ((ul_isr & GMAC_ISR_RCOMP) || (ul_rsr & GMAC_RSR_REC)) {
		ul_rx_status_flag = GMAC_RSR_REC;

		/* Check OVR */
		if (ul_rsr & GMAC_RSR_RXOVR) {
			ul_rx_status_flag |= GMAC_RSR_RXOVR;
		}
		/* Check BNA */
		if (ul_rsr & GMAC_RSR_BNA) {
			ul_rx_status_flag |= GMAC_RSR_BNA;
		}
		/* Clear status */
		gmac_clear_rx_status(p_hw, ul_rx_status_flag);

		/* Invoke callbacks */
		if (p_gmac_queue->func_rx_cb) {
			p_gmac_queue->func_rx_cb(ul_rx_status_flag);
		}
	}

	/* TX packet */
	if ((ul_isr & GMAC_ISR_TCOMP) || (ul_tsr & GMAC_TSR_TXCOMP)) {
		ul_tx_status_flag = GMAC_TSR_TXCOMP;

		/* Check RLE */
		if (ul_tsr & GMAC_TSR_RLE) {
			/* Status RLE */
			ul_tx_status_flag = GMAC_TSR_RLE;
			p_tx_cb = &p_gmac_queue->func_tx_cb_list[p_gmac_queue->us_tx_tail];
			gmac_reset_tx_mem(p_gmac_dev, queue_idx);
			gmac_enable_transmit(p_hw, 1);
		}
		/* Check COL */
		if (ul_tsr & GMAC_TSR_COL) {
			ul_tx_status_flag |= GMAC_TSR_COL;
		}

		/* Clear status */
		gmac_clear_tx_status(p_hw, ul_tx_status_flag);

		if (!CIRC_EMPTY(p_gmac_queue->us_tx_head, p_gmac_queue->us_tx_tail)) {
			/* Check the buffers */
			do {
				p_tx_td = &p_gmac_queue->p_tx_dscr[p_gmac_queue->us_tx_tail];
				p_tx_cb = &p_gmac_queue->func_tx_cb_list[p_gmac_queue->us_tx_tail];
				/* Any error? Exit if buffer has not been sent yet */
				if ((p_tx_td->status.val & GMAC_TXD_USED) == 0) {
					break;
				}

				/* Notify upper layer that a packet has been sent */
				if (*p_tx_cb) {
					(*p_tx_cb) (ul_tx_status_flag);
				}

				circ_inc(&p_gmac_queue->us_tx_tail, p_gmac_queue->us_tx_list_size);
			} while (CIRC_CNT(p_gmac_queue->us_tx_head, p_gmac_queue->us_tx_tail,
							p_gmac_queue->us_tx_list_size));
		}

		/* If a wakeup has been scheduled, notify upper layer that it can
		   send other packets, and the sending will be successful. */
		if ((CIRC_SPACE(p_gmac_queue->us_tx_head, p_gmac_queue->us_tx_tail,
				p_gmac_queue->us_tx_list_size) >= p_gmac_queue->uc_wakeup_threshold)
				&& p_gmac_queue->func_wakeup_cb) {
			p_gmac_queue->func_wakeup_cb();
		}
	}

#ifdef FREERTOS_USED
		/* Notify TCP/IP task to start data processing. */
		/* LwIP works on top of GMAC driver, hence this semaphore locks */
		/* the complete IP stack. */
		xSemaphoreGiveFromISR(netif_notification_semaphore,
				&xHigherPriorityTaskWoken);
		portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
#endif
}