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

📄 smscf.c

📁 dm642网络传输程序
💻 C
📖 第 1 页 / 共 2 页
字号:
    // Make sure we have a packet to send
    if( !(tx_hPkt = PBMQ_deq(&pi->PBMQ_tx)) )
    {
        pi->TxFree = 1;
        gmEnableIER( mask );
        return;
    }

    // Fill in the pending record
    tx_pBuffer = PBM_getDataBuffer(tx_hPkt);
    tx_Size    = PBM_getValidLen(tx_hPkt);
    tx_Offset  = PBM_getDataOffset(tx_hPkt);

    // Mark as "not free" and set TX state
    pi->TxFree = 0;

    // Clean the cache for external addesses
    if( (UINT32)tx_pBuffer & 0x80000000 )
        OEMCacheClean( (void *)(tx_pBuffer+tx_Offset), tx_Size );

    // Go into allocation phase
    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 | HW_IEDMAFLAG );

    // If not in the middle of a EDMA, check ints
    if( TxState != STATE_DMA && RxState != STATE_DMA )
    {
        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();
        }
    }

    // Check for DMA complete
    if( EDMA_intTest( EdmaEvent ) )
    {
        EdmaSave++;
        ICR = HW_IEDMAFLAG;
        EDMA_intClear( EdmaEvent );
        smscIsrEDMA(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 | HW_IEDMAFLAG );

    // 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;

    if( RxState == STATE_DMA )
        PBM_free( rx_hPkt );
    RxState = 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.
//--------------------------------------------------------------------
static void smscIsr()
{
    UINT8   pktnum;
    uint    IsrFlags;
    uint    IsrMask;

    IsrState = ISR_STATE_ACTIVE;

    if( TxState == STATE_DMA || RxState == STATE_DMA )
        goto IsrExit;

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

            // If in the middle of a EDMA, exit
            if( RxState == STATE_DMA )
                goto IsrExit;
        }

        if( IsrFlags & TX_EMPTY_INT )
        {
            TxState = STATE_IDLE;

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

            // If in the middle of a EDMA, exit
            if( TxState == STATE_DMA )
                goto IsrExit;
        }

        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 );

            // If in the middle of a EDMA, exit
            if( TxState == STATE_DMA )
                goto IsrExit;
        }

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

IsrExit:
    // Reset the ISR state
    IsrState = ISR_STATE_IDLE;

    // Renable SMSC interrupts.
    if( TxState != STATE_DMA && RxState != STATE_DMA )
        SMSC_WRITE8(SBA,SMSC_INT_MASK,IsrMask);
}

//--------------------------------------------------------------------
// smscSendPacket
//
// Send the packet (this function will free hFrag 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;

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

    // Set the current TX state, lock out other SMSC activity
    TxState = STATE_DMA;
    SMSC_WRITE8(SBA,SMSC_INT_MASK,0);
    ICR = HW_IFLAG;

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

    // Send any last byte(s) and the control word
    if( tx_Size < 2 )
        tx_Words = 1;
    else
    {
        tx_Words = 2;
        tx_Word1 = *buffer16++;
        tx_Size -= 2;
    }

    if( tx_Size )
        tx_Word2 = (*buffer16 & 0xFF) | (CONTROLBYTE_ODD<<8);
    else
        tx_Word2 = 0;
}

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

    SMSC_WRITE16(SBA,SMSC_BANK_SELECT,2);

    // Setup pointer to read, rcv, and auto_inc
    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 + -