⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fec.c

📁 Freescale MCF5445evb 参考测试代码
💻 C
📖 第 1 页 / 共 3 页
字号:
     */    MCF_FEC_PALR = (uint32)((pa[0]<<24) | (pa[1]<<16) | (pa[2]<<8) | pa[3]);    MCF_FEC_PAUR = (uint32)((pa[4]<<24) | (pa[5]<<16));    /*     * Calculate and set the hash for given Physical Address     * in the  Individual Address Hash registers     */    crc = fec_hash_address(pa);    if(crc >= 32)        MCF_FEC_IAUR |= (uint32)(1 << (crc - 32));    else        MCF_FEC_IALR |= (uint32)(1 << crc);}/********************************************************************//* * Reset the selected FEC controller * * Parameters: *  ch      FEC channel */voidfec_reset (int ch){    int i;    /* Set the Reset bit and clear the Enable bit */    MCF_FEC_ECR = MCF_FEC_ECR_RESET;    /* Wait at least 8 clock cycles */    for (i=0; i<10; ++i)        nop();}/********************************************************************//* * Initialize the selected FEC * * Parameters: *  ch      FEC channel *  mode    External interface mode (MII, 7-wire, or internal loopback) *  duplex  Duplex setting (FEC_MII_FULL_DUPLEX or FEC_MII_HALF_DUPLEX) *  prom    Promiscuous mode setting (ON/TRUE or OFF/FALSE) *  pa      Physical (Hardware) Address for the selected FEC */voidfec_init (int ch, int mode, MII_DUPLEX duplex, int prom, const uint8* pa){    /* Enable all the external interface signals */    if (mode == FEC_MODE_7WIRE)    {        MCF_GPIO_PTIPAR = MCF_GPIO_PTIPAR_FEC_COL_FEC_COL//						| MCF_GPIO_PTIPAR_FEC_CRS_FEC_CRS						| MCF_GPIO_PTIPAR_FEC_RXCLK_FEC_RXCLK						| MCF_GPIO_PTIPAR_FEC_RXD0_FEC_RXD0//						| MCF_GPIO_PTIPAR_FEC_RXD1_FEC_RXD1//						| MCF_GPIO_PTIPAR_FEC_RXD2_FEC_RXD2//						| MCF_GPIO_PTIPAR_FEC_RXD3_FEC_RXD3						| MCF_GPIO_PTIPAR_FEC_RXDV_FEC_RXDV;		MCF_GPIO_PTJPAR = //MCF_GPIO_PTJPAR_FEC_RXER_FEC_RXER						  MCF_GPIO_PTJPAR_FEC_TXCLK_FEC_TXCLK						| MCF_GPIO_PTJPAR_FEC_TXD0_FEC_TXD0//						| MCF_GPIO_PTJPAR_FEC_TXD1_FEC_TXD1//						| MCF_GPIO_PTJPAR_FEC_TXD2_FEC_TXD2//						| MCF_GPIO_PTJPAR_FEC_TXD3_FEC_TXD3						| MCF_GPIO_PTJPAR_FEC_TXEN_FEC_TXEN;//						| MCF_GPIO_PTJPAR_FEC_TXER_FEC_TXER;    }    else if (mode == FEC_MODE_MII)    {        MCF_GPIO_PTIPAR = MCF_GPIO_PTIPAR_FEC_COL_FEC_COL						| MCF_GPIO_PTIPAR_FEC_CRS_FEC_CRS						| MCF_GPIO_PTIPAR_FEC_RXCLK_FEC_RXCLK						| MCF_GPIO_PTIPAR_FEC_RXD0_FEC_RXD0						| MCF_GPIO_PTIPAR_FEC_RXD1_FEC_RXD1						| MCF_GPIO_PTIPAR_FEC_RXD2_FEC_RXD2						| MCF_GPIO_PTIPAR_FEC_RXD3_FEC_RXD3						| MCF_GPIO_PTIPAR_FEC_RXDV_FEC_RXDV;		MCF_GPIO_PTJPAR = MCF_GPIO_PTJPAR_FEC_RXER_FEC_RXER						| MCF_GPIO_PTJPAR_FEC_TXCLK_FEC_TXCLK						| MCF_GPIO_PTJPAR_FEC_TXD0_FEC_TXD0						| MCF_GPIO_PTJPAR_FEC_TXD1_FEC_TXD1						| MCF_GPIO_PTJPAR_FEC_TXD2_FEC_TXD2						| MCF_GPIO_PTJPAR_FEC_TXD3_FEC_TXD3						| MCF_GPIO_PTJPAR_FEC_TXEN_FEC_TXEN						| MCF_GPIO_PTJPAR_FEC_TXER_FEC_TXER;    }    else if (mode == FEC_MODE_RMII)    {        ASSERT(FALSE);    }    else    {        /*  oops */        ASSERT(FALSE);    }            /* Clear the Individual and Group Address Hash registers */    MCF_FEC_IALR = 0;    MCF_FEC_IAUR = 0;    MCF_FEC_GALR = 0;    MCF_FEC_GAUR = 0;    /* Set the Physical Address for the selected FEC */    fec_set_address(ch, pa);    /* Set Rx Buffer Size */    MCF_FEC_EMRBR = (uint16)RX_BUF_SZ;    /* Point to the start of the circular Rx buffer descriptor queue */    MCF_FEC_ERDSR = fecbd_get_start(ch, Rx);    /* Point to the start of the circular Tx buffer descriptor queue */    MCF_FEC_ETSDR = fecbd_get_start(ch, Tx);    /* Mask all FEC interrupts */    MCF_FEC_EIMR = MCF_FEC_EIMR_MASK_ALL;    /* Clear all FEC interrupt events */    MCF_FEC_EIR = MCF_FEC_EIR_CLEAR_ALL;    /* Initialize the Receive Control Register */    MCF_FEC_RCR = 0        | MCF_FEC_RCR_MAX_FL(ETH_MAX_FRM)        | MCF_FEC_RCR_FCE;    if (mode == FEC_MODE_MII)        MCF_FEC_RCR |= MCF_FEC_RCR_MII_MODE;    else if (mode == FEC_MODE_LOOPBACK)        MCF_FEC_RCR |= (MCF_FEC_RCR_LOOP | MCF_FEC_RCR_PROM);        if (prom)        MCF_FEC_RCR |= MCF_FEC_RCR_PROM;    /* Set the duplex */    if (mode == FEC_MODE_LOOPBACK)        /* Loopback mode must operate in full-duplex */        fec_duplex(ch, MII_FDX);    else        fec_duplex(ch, duplex);}/********************************************************************//* * Continue the Rx DMA task * * This routine is called after the DMA task has halted after * encountering an Rx buffer descriptor that wasn't marked as * ready. There is no harm in calling the DMA continue routine * if the DMA is not halted. * * Parameters: *  ch      FEC channel */voidfec_rx_continue(int ch){    /*  Continue/restart the FEC DMA */    MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;}/********************************************************************//* * Receive Frame interrupt handler * * Parameters: *  nif     Pointer to Network Interface structure */voidfec_rx_handler(NIF *nif){    ETH_HDR *eth_hdr;    FECBD *pRxBD;    NBUF *cur_nbuf, *new_nbuf;    int keep;    int i = 0;    while ((pRxBD = fecbd_rx_alloc(nif->ch)) != NULL)    {        keep = TRUE;        if (pRxBD->status & RX_BD_L)            fec_log[nif->ch].rxf++;        else            fec_log[nif->ch].rxb++;                if (pRxBD->status & RX_BD_ERROR)        {           // keep = FALSE; //mask for UN test            if (pRxBD->status & RX_BD_NO)                fec_log[nif->ch].rfsw_no++;            if (pRxBD->status & RX_BD_CR)                fec_log[nif->ch].rfsw_cr++;            if (pRxBD->status & RX_BD_OV)                fec_log[nif->ch].rfsw_ov++;            if (pRxBD->status & RX_BD_TR)                fec_log[nif->ch].rfsw_tr++;        }        else        {            if (pRxBD->status & RX_BD_LG)                fec_log[nif->ch].rfsw_lg++;            if (pRxBD->status & RX_BD_M)                fec_log[nif->ch].rfsw_m++;            if (pRxBD->status & RX_BD_BC)                fec_log[nif->ch].rfsw_bc++;            if (pRxBD->status & RX_BD_MC)                fec_log[nif->ch].rfsw_mc++;        }        if (keep)        {            /* Pull the network buffer off the Rx ring queue */            cur_nbuf = (NBUF *)queue_remove(&rxbd_queue[nif->ch]);            ASSERT(cur_nbuf);            ASSERT(cur_nbuf->data == pRxBD->data);            /* Copy the buffer descriptor information to the network buffer */            cur_nbuf->length = (pRxBD->length - (ETH_HDR_LEN + ETH_CRC_LEN));            cur_nbuf->offset = ETH_HDR_LEN;            /* Get a new buffer pointer for this buffer descriptor */            new_nbuf = nbuf_alloc();            if (new_nbuf == NULL)            {                #ifdef DEBUG_PRINT                    printf("nbuf_alloc() failed\n");                #endif                /*                 * Can't allocate a new network buffer, so we are                  * going to trash the received data and reuse the buffer                 * hoping that some buffers will free up in the system                 * and this frame will be re-transmitted by the host                 */                pRxBD->length = RX_BUF_SZ;                pRxBD->status &= RX_BD_W;                pRxBD->status |= RX_BD_E;                queue_add(&rxbd_queue[nif->ch],(QNODE *)cur_nbuf);                fec_rx_continue(nif->ch);                continue;            }            /* Add the new network buffer to the Rx ring queue */            queue_add(&rxbd_queue[nif->ch],(QNODE *)new_nbuf);            /*             * Re-initialize the buffer descriptor - pointing it             * to the new data buffer.  The previous data buffer             * will be passed up the stack             */            pRxBD->data = new_nbuf->data;            pRxBD->length = RX_BUF_SZ;            pRxBD->status &= (RX_BD_W);            pRxBD->status |= RX_BD_E;            /* Let the DMA know that there is a new Rx BD (in case the              * ring was full and the DMA was waiting for an empty one) */            fec_rx_continue(nif->ch);            /* Get pointer to the frame data inside the network buffer */            eth_hdr = (ETH_HDR *)cur_nbuf->data;                        /* Pass the received packet up the network stack if the              * protocol is supported in our network interface (NIF) */            if (nif_protocol_exist(nif,eth_hdr->type))            {                nif_protocol_handler(nif, eth_hdr->type, cur_nbuf);            }            //else    modify by LK            nbuf_free(cur_nbuf);        }        else         {            /* This frame isn't a keeper             * Reset the status and length, but don't need to get another             * buffer since we are trashing the data in the current one */            pRxBD->length = RX_BUF_SZ;            pRxBD->status &= (RX_BD_W);            pRxBD->status |= RX_BD_E;            /* Move the current buffer from the beginning to the end of the              * Rx ring queue */            cur_nbuf = (NBUF *)queue_remove(&rxbd_queue[nif->ch]);            queue_add(&rxbd_queue[nif->ch],(QNODE *)cur_nbuf);            /* Let the DMA know that there are new Rx BDs (in case             * it is waiting for an empty one) */            fec_rx_continue(nif->ch);        }    }}/********************************************************************//* * Continue the Tx DMA task * * This routine is called after the DMA task has halted after * encountering an Tx buffer descriptor that wasn't marked as * ready.  There is no harm in calling the continue DMA routine * if the DMA was not paused. * * Parameters: *  ch      FEC channel */voidfec_tx_continue(int ch){    /* Continue/restart the FEC DMA */    MCF_FEC_TDAR = MCF_FEC_TDAR_X_DES_ACTIVE;}/********************************************************************//* * Stop all transmissions on the selected FEC and kill the DMA task * * Parameters: *  ch  FEC channel */voidfec_tx_stop (int ch){    uint32 mask;    int i, channel;    /* Save off the EIMR value */    mask = MCF_FEC_EIMR;    /* Mask all interrupts */    MCF_FEC_EIMR = 0;    /* If the Ethernet is still enabled... */    if (MCF_FEC_ECR & MCF_FEC_ECR_ETHER_EN)    {        /* Issue the Graceful Transmit Stop */        MCF_FEC_TCR |= MCF_FEC_TCR_GTS;        /* Wait for the Graceful Stop Complete interrupt */        i = 500000;        while(!(MCF_FEC_EIR & MCF_FEC_EIR_GRA))        {            if (!(MCF_FEC_ECR & MCF_FEC_ECR_ETHER_EN))                break;            if (--i == 0)                break;        }        /* Clear the Graceful Stop Complete interrupt */        MCF_FEC_EIR = MCF_FEC_EIR_GRA;    }    /* Restore the interrupt mask register value */    MCF_FEC_EIMR = mask;}/********************************************************************//* * Trasmit Frame interrupt handler - this handler is called when an * FEC Tx interrupt event occurs * * Parameters: *  ch      FEC channel *  event   Other interrupt events at the time of the Tx interrupt */voidfec_tx_handler(NIF* nif, int event){    FECBD *pTxBD;    NBUF *pNbuf;    int i = 0;    /*      * Here is where we could check "event" to see if any errors      * occurred during transmission.  If the Tx interrupt isn't serviced     * before a second packet is sent, then it will not be possible to      * determine which events correspond to which packet(s).     */    (void) event;        while ((pTxBD = fecbd_tx_free(nif->ch)) != NULL)    {        if (pTxBD->status & TX_BD_L)            fec_log[nif->ch].txf++;        else            fec_log[nif->ch].txb++;                /* Grab the network buffer associated with this descriptor */        pNbuf = (NBUF *)queue_remove(&txbd_queue[nif->ch]);        ASSERT(pNbuf);        ASSERT(pNbuf->data == pTxBD->data);        /* If there is a Tx callback function enabled, call it and pass         * it the pointer to the packet that was just transmitted.  If not,         * free the network buffer now.  If there is a callback function,          * it is responsible for freeing the network buffer! */        if (nif[nif->ch].txcallback != NULL)        {            nif[nif->ch].txcallback(pNbuf);        }        else        {            /* Free up the network buffer that was just transmitted */            nbuf_free(pNbuf);        }                /* Check for packets in the send holding queue */        pNbuf = (NBUF *)queue_remove(&send_queue[nif->ch]);                if (pNbuf != NULL)        {   /* There was a packet waiting in the send queue */            /* Put the buffer into the TxBD ring queue */            queue_add(&txbd_queue[nif->ch],(QNODE *)pNbuf);            /* Setup the buffer descriptor for transmission */            pTxBD->data = pNbuf->data;            pTxBD->length = pNbuf->length + ETH_HDR_LEN;            pTxBD->status |= (TX_BD_R | TX_BD_L);            /* Kick the Tx DMA */            fec_tx_continue(nif->ch);        }        else        {   /* There is nothing in the send holding queue */            /* Re-initialize the Tx BD to empty */            pTxBD->data = NULL;            pTxBD->length = 0;        }    }}/********************************************************************//* * Send a packet out the selected FEC *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -