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

📄 emac.c

📁 keil for at91sam9263ek ads and emac编程
💻 C
📖 第 1 页 / 共 3 页
字号:
{
    AT91C_BASE_EMAC->EMAC_MAN = (AT91C_EMAC_SOF & (0x01 << 30))
                              | (AT91C_EMAC_CODE & (2 << 16))
                              | (AT91C_EMAC_RW & (2 << 28))
                              | (AT91C_EMAC_PHYA & ((PhyAddress & 0x1f) << 23))
                              | (AT91C_EMAC_REGA & (Address << 18));

    if ( EMAC_WaitPhy(retry) == 0 ) {

        TRACE_ERROR("TimeOut EMAC_ReadPhy\n\r");
        return 0;
    }
    *pValue = ( AT91C_BASE_EMAC->EMAC_MAN & 0x0000ffff );
    return 1;
}

//-----------------------------------------------------------------------------
/// Write PHY register
/// Return 1 if successfully, 0 if timeout.
/// \param PhyAddress PHY Address
/// \param Address Register Address
/// \param Value Data to write ( Actually 16 bit data )
/// \param retry The retry times, 0 to wait forever until complete.
//-----------------------------------------------------------------------------
unsigned char EMAC_WritePhy(unsigned char PhyAddress,
                            unsigned char Address,
                            unsigned int  Value,
                            unsigned int  retry)
{
    AT91C_BASE_EMAC->EMAC_MAN = (AT91C_EMAC_SOF & (0x01 << 30))
                              | (AT91C_EMAC_CODE & (2 << 16))
                              | (AT91C_EMAC_RW & (1 << 28))
                              | (AT91C_EMAC_PHYA & ((PhyAddress & 0x1f) << 23))
                              | (AT91C_EMAC_REGA & (Address << 18))
                              | (AT91C_EMAC_DATA & Value) ;
    if ( EMAC_WaitPhy(retry) == 0 ) {

        TRACE_ERROR("TimeOut EMAC_WritePhy\n\r");
        return 0;
    }
    return 1;
}

//-----------------------------------------------------------------------------
/// Setup the EMAC for the link : speed 100M/10M and Full/Half duplex
/// \param speed        Link speed, 0 for 10M, 1 for 100M
/// \param fullduplex   1 for Full Duplex mode
//-----------------------------------------------------------------------------
void EMAC_SetLinkSpeed(unsigned char speed, unsigned char fullduplex)
{
    unsigned int ncfgr;

    ncfgr = AT91C_BASE_EMAC->EMAC_NCFGR;
    ncfgr &= ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
    if (speed) {

        ncfgr |= AT91C_EMAC_SPD;
    }
    if (fullduplex) {

        ncfgr |= AT91C_EMAC_FD;
    }
    AT91C_BASE_EMAC->EMAC_NCFGR = ncfgr;
}



//-----------------------------------------------------------------------------
//          EMAC functions
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
/// 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();
        }
    }
}

//-----------------------------------------------------------------------------
/// Initialize the EMAC with the emac controller address
/// \param id     HW ID for power management
/// \param pTxWakeUpfct Thresold TX Wakeup Callback
/// \param pRxfct       RX Wakeup Callback
/// \param pMacAddress  Mac Address
/// \param enableCAF    enable AT91C_EMAC_CAF if needed by application
/// \param enableNBC    AT91C_EMAC_NBC if needed by application
//-----------------------------------------------------------------------------
void EMAC_Init( unsigned char id, const unsigned char *pMacAddress, 
                unsigned char enableCAF, unsigned char enableNBC )
{
    int Index;
    unsigned int Address;

    // Check parameters
    ASSERT(RX_BUFFERS * EMAC_RX_UNITSIZE > EMAC_FRAME_LENTGH_MAX,
           "E: RX buffers too small\n\r");

    TRACE_DEBUG("EMAC_Init\n\r");

    // Power ON
    AT91C_BASE_PMC->PMC_PCER = 1 << id;

    // Disable TX & RX and more
    AT91C_BASE_EMAC->EMAC_NCR = 0;

    // disable 
    AT91C_BASE_EMAC->EMAC_IDR = ~0;

    rxTd.idx = 0;
    CIRC_CLEAR(&txTd);

    // Setup the RX descriptors.
    for(Index = 0; Index < RX_BUFFERS; Index++) {

        Address = (unsigned int)(&(pRxBuffer[Index * EMAC_RX_UNITSIZE]));
        // Remove EMAC_RX_OWNERSHIP_BIT and EMAC_RX_WRAP_BIT
        rxTd.td[Index].addr = Address & EMAC_ADDRESS_MASK;
        rxTd.td[Index].status = 0;
    }
    rxTd.td[RX_BUFFERS - 1].addr |= EMAC_RX_WRAP_BIT;

    // Setup the TX descriptors.
    for(Index = 0; Index < TX_BUFFERS; Index++) {

        Address = (unsigned int)(&(pTxBuffer[Index * EMAC_TX_UNITSIZE]));
        txTd.td[Index].addr = Address;
        txTd.td[Index].status = EMAC_TX_USED_BIT;
    }
    txTd.td[TX_BUFFERS - 1].status = EMAC_TX_USED_BIT | EMAC_TX_WRAP_BIT;

    // Set the MAC address
    if( pMacAddress != (unsigned char *)0 ) {
        AT91C_BASE_EMAC->EMAC_SA1L = ( ((unsigned int)pMacAddress[3] << 24)
                                     | ((unsigned int)pMacAddress[2] << 16)
                                     | ((unsigned int)pMacAddress[1] << 8 )
                                     |                pMacAddress[0] );

        AT91C_BASE_EMAC->EMAC_SA1H = ( ((unsigned int)pMacAddress[5] << 8 )
                                     |                pMacAddress[4] );
    }
    // Now setup the descriptors
    // Receive Buffer Queue Pointer Register
    AT91C_BASE_EMAC->EMAC_RBQP = (unsigned int) (rxTd.td);
    // Transmit Buffer Queue Pointer Register
    AT91C_BASE_EMAC->EMAC_TBQP = (unsigned int) (txTd.td);

    AT91C_BASE_EMAC->EMAC_NCR = AT91C_EMAC_CLRSTAT;

    // Clear all status bits in the receive status register.
    AT91C_BASE_EMAC->EMAC_RSR = (AT91C_EMAC_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA);

    // Clear all status bits in the transmit status register
    AT91C_BASE_EMAC->EMAC_TSR = ( AT91C_EMAC_UBR | AT91C_EMAC_COL | AT91C_EMAC_RLES
                                | AT91C_EMAC_BEX | AT91C_EMAC_COMP
                                | AT91C_EMAC_UND );

    // Clear interrupts
    AT91C_BASE_EMAC->EMAC_ISR;

    // Enable the copy of data into the buffers
    // ignore broadcasts, and don't copy FCS.
    AT91C_BASE_EMAC->EMAC_NCFGR |= (AT91C_EMAC_DRFCS | AT91C_EMAC_PAE);

    if( enableCAF == EMAC_CAF_ENABLE ) {
        AT91C_BASE_EMAC->EMAC_NCFGR |= AT91C_EMAC_CAF;
    }
    if( enableNBC == EMAC_NBC_ENABLE ) {
        AT91C_BASE_EMAC->EMAC_NCFGR |= AT91C_EMAC_NBC;
    }

    // Enable Rx and Tx, plus the stats register.
    AT91C_BASE_EMAC->EMAC_NCR |= (AT91C_EMAC_TE | AT91C_EMAC_RE | AT91C_EMAC_WESTAT);

    // Setup the interrupts for TX (and errors)
    AT91C_BASE_EMAC->EMAC_IER = AT91C_EMAC_RXUBR
                              | AT91C_EMAC_TUNDR
                              | AT91C_EMAC_RLEX
                              | AT91C_EMAC_TXERR
                              | AT91C_EMAC_TCOMP
                              | AT91C_EMAC_ROVR

⌨️ 快捷键说明

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