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

📄 smsce.c

📁 dm642网络传输程序
💻 C
📖 第 1 页 / 共 2 页
字号:
    TxState = STATE_ALLOC_PEND;

    // Allocate a transmit buffer
    // Assume ALLOC_INT is already masked
    SMSC_WRITE16(SBA,SMSC_BANK_SELECT,2);

    // Make sure busy bit is low
    while( SMSC_READ16(SBA,SMSC_MMU_COMMAND) & BUSY_BIT );

    // Send the allocate command
    SMSC_WRITE16(SBA,SMSC_MMU_COMMAND,CMD_ALLOCATE_MEMORY);

    // Make sure busy bit is low
    while( SMSC_READ16(SBA,SMSC_MMU_COMMAND) & BUSY_BIT );

    // Check results. If packet has been allocated, we can fill
    // the TX FIFO and send now.
    tempbyte = SMSC_READ8(SBA,SMSC_ALLOC_RESULT);
    if( !(tempbyte & FAILED) )
    {
        // Send the packet (this function will free hFrag and set the
        // TxState back to IDLE). The value of "tempbyte" is the SMSC
        // packet number.
        smscSendPacket( tempbyte );
        goto tx_exit;
    }

    // If we get here, the allocation is pending and we remain in the
    // TX_STATE_ALLOC_PEND state. If called from an ISR, we just return
    // since the ISR will handle the INT mask stuff. If not in an ISR,
    // we need to enable the ALLOC_INT interrupt.
    if( IsrState == ISR_STATE_IDLE )
    {
        tempbyte = SMSC_READ8(SBA,SMSC_INT_MASK) | ALLOC_INT;
        SMSC_WRITE8(SBA,SMSC_INT_MASK,tempbyte);
    }

tx_exit:
    // (Potentially) re-enable SMSC device interrupts on the DSP
    gmEnableIER( mask );
}

//--------------------------------------------------------------------
// _HwPktPoll()
//
// Poll routine - CALLED OUTSIDE OF KERNEL MODE
//
// This function is called at least every 100ms, faster in a
// polling environment. The fTimerTick flag is set only when
// called on a 100ms event.
//--------------------------------------------------------------------
void _HwPktPoll( PDINFO *pi, uint fTimerTick )
{
    uint   mask;

    (void)pi;

    if( fTimerTick )
    {
        LED_TOGGLE( USER_LED2 );
        if( FlashActiveLED )
        {
            FlashActiveLED = 0;
            LED_TOGGLE( USER_LED3 );
        }
    }

    // Get into kernel mode to be safe
    llEnter();

    // Make sure our int is disabled
    mask = gmDisableIER( HW_IFLAG );

    // Check for missed interrupt
    SMSC_WRITE16(SBA,SMSC_BANK_SELECT,2);
    if( SMSC_READ8(SBA,SMSC_INT_MASK) & SMSC_READ8(SBA,SMSC_INT_STATUS) )
    {
        IntSave++;
        ICR = HW_IFLAG;
        smscIsr(0);
    }

    // (Potentially) re-enable SMSC device interrupts on the DSP
    gmEnableIER( mask );

    // Leave kernel mode
    llExit();
}

//--------------------------------------------------------------------
// smscReset()
//
// Reset MAC, initialize, and prepare to start
//--------------------------------------------------------------------
static void smscReset()
{
    UINT16 tmpword;
    UINT8  tmpbyte;

    // Set the default configuration
    SMSC_WRITE16(SBA,SMSC_BANK_SELECT,1);
    SMSC_WRITE16(SBA,SMSC_CONFIGURATION,CONFIGURATION_DEFAULT);

    // Soft reset
    SMSC_WRITE16(SBA,SMSC_BANK_SELECT,0);
    SMSC_WRITE16(SBA,SMSC_RECEIVE_CONTROL,SOFT_RST);
    Delay(10000);
    SMSC_WRITE16(SBA,SMSC_RECEIVE_CONTROL,0);
    Delay(10000);

    // Setup Auto-negotiation on the PHY and program the LEDs to
    // be tx/rx indicator on 2 and 10/100 link indicator on 1
    SMSC_WRITE16(SBA,SMSC_PHY_CONTROL,ANEG|LS1A|LS0A);

    // Setup auto-release on the conrol reg
    SMSC_WRITE16(SBA,SMSC_BANK_SELECT,1);
    tmpword = SMSC_READ16(SBA,SMSC_CONTROL) | AUTO_RELEASE;
    SMSC_WRITE16(SBA,SMSC_CONTROL,tmpword);

    // Reset the MMU
    SMSC_WRITE16(SBA,SMSC_BANK_SELECT,2);

    // Make sure busy bit is low
    while( SMSC_READ16(SBA,SMSC_MMU_COMMAND) & BUSY_BIT );

    SMSC_WRITE16(SBA,SMSC_MMU_COMMAND,CMD_RESET_MMU);

    // Make sure busy bit is low
    while( SMSC_READ16(SBA,SMSC_MMU_COMMAND) & BUSY_BIT );

    // Setup interrupt mask
    SMSC_WRITE8(SBA,SMSC_INT_MASK,0);

    // Ack any pending interrupts
    tmpbyte = SMSC_READ8(SBA,SMSC_INT_STATUS);
    SMSC_WRITE8(SBA,SMSC_INT_STATUS,tmpbyte);

    // Setup interrupt mask
    SMSC_WRITE8(SBA,SMSC_INT_MASK,TX_INT|RCV_INT);

    // Enable Transmitter
    SMSC_WRITE16(SBA,SMSC_BANK_SELECT,0);
    SMSC_WRITE16(SBA,SMSC_TRANSMIT_CONTROL,TransmitControl);

    // Reset the PHY negotiation
    smscWritePHY( 0, 0x3200 );

    // Tansmitter is not free until we start
    pPDI->TxFree = 0;

    // Delay for a bit
    Delay(3000000);
}

//--------------------------------------------------------------------
// smscStart()
//
// Start MAC Rx and Tx state machines
//--------------------------------------------------------------------
static void smscStart()
{
    // Initialize states
    TxState = STATE_IDLE;
    pPDI->TxFree = 1;

    // Setup Rx Filter Mode
    HwPktSetRx( pPDI );

    // Start receive
    SMSC_WRITE16(SBA,SMSC_BANK_SELECT,0);
    SMSC_WRITE16(SBA,SMSC_RECEIVE_CONTROL,RXEN);
}

//--------------------------------------------------------------------
// smscStop()
//
// Stop GMAC, abort current Rx and Tx
//--------------------------------------------------------------------
static void smscStop()
{
    uint mask;

    // Disable interrupts from device
    mask = gmDisableIER( HW_IFLAG );

    // Stop anyone from entering HwPktTxNext()
    pPDI->TxFree = 0;

    // Reset the part
    smscReset();

    // Clean up any waiting TX frag
    if( TxState != STATE_IDLE && TxState != STATE_SEND )
        PBM_free( tx_hPkt );
    TxState = STATE_IDLE;

    // Re-enable the part
    gmEnableIER( mask );

    // Flush the Tx Queue
    while( PBMQ_count(&pPDI->PBMQ_tx) )
        PBM_free( PBMQ_deq(&pPDI->PBMQ_tx) );
}

//--------------------------------------------------------------------
// smscIsr()
//
// General purpose ISR function.
//
// The calling arg "fTrueInt" is set to "1" if called at
// interrupt time, "0" otherwise.
//--------------------------------------------------------------------
static void smscIsr( UINT32 fTrueInt )
{
    UINT8   pktnum;
    uint    IsrFlags;
    uint    IsrMask;
    uint    needevent = 0;

    IsrState = ISR_STATE_ACTIVE;

    // Mask all interrupts while in the ISR. This will also drive
    // the SMSC interrupt low, allowing the DSP to catch the rising
    // edge of the line if interrupts are still pending when we try
    // to exit the ISR.
    SMSC_WRITE16(SBA,SMSC_BANK_SELECT,2);
    SMSC_WRITE8(SBA,SMSC_INT_MASK,0);

    do
    {
        // Now process all pending interrupts
        IsrFlags = SMSC_READ8(SBA,SMSC_INT_STATUS);

        if( RxState == STATE_IDLE )
            IsrMask = TX_INT|RCV_INT;
        else
            IsrMask = TX_INT;

        if( TxState == STATE_ALLOC_PEND )
            IsrMask |= ALLOC_INT;
        else if( TxState == STATE_SEND )
            IsrMask |= TX_EMPTY_INT;

        IsrFlags &= ( IsrMask | RX_OVRN_INT );

        // Count overruns for debug
        if( IsrFlags & RX_OVRN_INT )
            RxOver++;

        if( IsrFlags & TX_INT )
        {
            TxBad++;

            // Get the packet number of the failed packet
            pktnum = SMSC_READ8(SBA,SMSC_TX_FIFO_PACKET);

            // Make sure busy bit is low
            while( SMSC_READ16(SBA,SMSC_MMU_COMMAND) & BUSY_BIT );

            // Free this packet
            SMSC_WRITE8(SBA,SMSC_PACKET_NUMBER,pktnum);
            SMSC_WRITE16(SBA,SMSC_MMU_COMMAND,CMD_RELEASE_PACKET);

            // Make sure busy bit is low
            while( SMSC_READ16(SBA,SMSC_MMU_COMMAND) & BUSY_BIT );

            // Start the transmitter
            SMSC_WRITE16(SBA,SMSC_BANK_SELECT,0);
            SMSC_WRITE16(SBA,SMSC_TRANSMIT_CONTROL,TransmitControl);
        }

        if( IsrFlags & RCV_INT )
        {
            // Handle packet receive
            needevent |= smscReceivePacket();
        }

        if( IsrFlags & TX_EMPTY_INT )
        {
            TxState = STATE_IDLE;

            // See if there is another packet pending
            HwPktTxNext( pPDI );
        }

        if( IsrFlags & ALLOC_INT )
        {
            // Make sure we're on bank 2
            SMSC_WRITE16(SBA,SMSC_BANK_SELECT,2);

            // Get packet number (we now know the alloc is OK)
            // We can fill the TX FIFO and send now.
            pktnum = SMSC_READ8(SBA,SMSC_ALLOC_RESULT);

            // Send the packet (this function will free hPkt and set the
            // TxState back to IDLE). The value of "pktnum" is the SMSC
            // packet number.
            smscSendPacket( pktnum );
        }

        // Make sure we're on bank 2
        SMSC_WRITE16(SBA,SMSC_BANK_SELECT,2);

        // Ack the interrupt
        SMSC_WRITE8(SBA,SMSC_INT_STATUS,IsrFlags);

    } while( IsrFlags );

    // Reset the ISR state
    IsrState = ISR_STATE_IDLE;

    // Renable SMSC interrupts.
    SMSC_WRITE8(SBA,SMSC_INT_MASK,IsrMask);

    // Post the NETCTRL event semaphore when needed
    if( needevent )
    {
        FlashActiveLED = 1;
        STKEVENT_signal( pPDI->hEvent, STKEVENT_ETHERNET, fTrueInt );
    }
}

//--------------------------------------------------------------------
// smscSendPacket
//
// Send the packet (this function will free hPkt and set the
// TxState back to IDLE). The SMSC packet number is passed as
// the calling parameter
//
// If the packet is not properly aligned, it will align it
//--------------------------------------------------------------------
static void smscSendPacket( UINT8 smscPacketNumber )
{
    UINT16 *buffer16;
    UINT16 tempword;
    UINT8  tempbyte;

    // First, set the current TX state
    TxState = STATE_DMA;

    // Load the transmit data
    SMSC_WRITE16(SBA,SMSC_BANK_SELECT,2);
    SMSC_WRITE8(SBA,SMSC_PACKET_NUMBER,smscPacketNumber);

    // Setup pointer (write and TX are default)
    while( NOT_EMPTY & SMSC_READ16( SBA, SMSC_POINTER ) ) {
        ; // wait for write FIFO to become empty
    }
    SMSC_WRITE16(SBA,SMSC_POINTER,AUTO_INCR);

    // Write the status word
    SMSC_WRITE16(SBA,SMSC_DATA,0);

    // Write the packet size (byte count)
    SMSC_WRITE16(SBA,SMSC_DATA,(tx_Size & ~1)+6 );

    tempword = tx_Size>>2;

    // Setup EDMA
    EDMA_RSETH(hEDMA,OPT,EdmaOptTx);
    EDMA_RSETH(hEDMA,SRC,(UINT32)(tx_pBuffer + tx_Offset));
    EDMA_RSETH(hEDMA,CNT,tempword);
    EDMA_RSETH(hEDMA,DST,(SBA+SMSC_DATA));

    // Synch the cache
    if( (UINT32)tx_pBuffer & 0x80000000 )
        OEMCacheCleanSynch();

    // Make sure the status word and packet size writes got to the
    // SMSC. We do this by reading the SMSC device.
    SMSC_READ16(SBA,SMSC_BANK_SELECT);

    // Start the DMA
    EDMA_setChannel(hEDMA);

    // Setup for final transfer
    tempword <<= 2;
    tx_Size -= tempword;
    buffer16 = (UINT16 *)(tx_pBuffer + tx_Offset + tempword);

    // Wait for DMA to complete
    while( !EDMA_intTest( EdmaEvent ) );
    EDMA_intClear( EdmaEvent );

    // Send 2 bytes at a time for one go
    if( tx_Size >= 2 )
    {
        SMSC_WRITE16(SBA,SMSC_DATA,*buffer16++);
        tx_Size -= 2;
    }

    // Send any last byte and the control word
    if( tx_Size )
        tempword = (*buffer16 & 0xFF) | (CONTROLBYTE_ODD<<8);
    else
        tempword = 0;

    SMSC_WRITE16(SBA,SMSC_DATA,tempword);

    // Make sure busy bit is low
    while( SMSC_READ16(SBA,SMSC_MMU_COMMAND) & BUSY_BIT );

    // Enqueue the packet
    SMSC_WRITE16(SBA,SMSC_MMU_COMMAND,CMD_ENQUEUE_PACKET);

    // Make sure busy bit is low
    while( SMSC_READ16(SBA,SMSC_MMU_COMMAND) & BUSY_BIT );

    // Assume its a good transmit
    TxGood++;

    // Now we can free the packet
    PBM_free( tx_hPkt );

    // Set the transmitter state to SEND
    TxState = STATE_SEND;

    // We need an interrupt when this packet has been sent
    if( IsrState == ISR_STATE_IDLE )
    {
        tempbyte = SMSC_READ8(SBA,SMSC_INT_MASK) | TX_EMPTY_INT;
        SMSC_WRITE8(SBA,SMSC_INT_MASK,tempbyte);
    }
}

//--------------------------------------------------------------------
// smscReceivePacket()
//
// This function hanldes all RCV interrupt conditions
//
// Returns 1 if one or more packets received, or 0 on
// error condition.
//--------------------------------------------------------------------
static uint smscReceivePacket()
{
    UINT16      tempword,size;
    UINT16      *buffer16;
    PBM_Handle  hPkt;
    uint        retval = 0;
    UINT8       *pData;

    // First, set the current RX state
    RxState = STATE_DMA;

    // Setup pointer to read, rcv, and auto_inc
    SMSC_WRITE16(SBA,SMSC_BANK_SELECT,2);
    while( NOT_EMPTY & SMSC_READ16( SBA, SMSC_POINTER ) ) {
        ; // wait for write FIFO to become empty
    }
    SMSC_WRITE16(SBA,SMSC_POINTER,RCV|READ|AUTO_INCR);

    // wait 370 ns 

⌨️ 快捷键说明

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