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

📄 emac.c

📁 这是基于TI公司的DSP TMS320DM642而开发的TCP/UDP协议
💻 C
字号:
#include "Emac.h"
#include "eth.h"


//---------Raw Data Buffers----------
//
// This program uses internal memory, so buffer size is 
// just 1518 In order to make sure buffers are cache 
// aligned, if each were in cacheable external memory 
// the size should be at least 1536 so as to fill enitre 
// cache line.

#define PKT_MAX 32

#pragma DATA_SECTION(packet_header, ".ExtDat1");

EMAC_Pkt packet_header[PKT_MAX];

#pragma DATA_SECTION(packet_buffer, ".ExtDat1");
Uint8 packet_buffer[PKT_MAX][1536];

EMAC_Config  g_emacConfig;


PKTQ     FreeQueue;        // Free packets for RX or Tx
PKTQ     RxQueue;          // Received packets 


// Declare some local status variables
Handle    hEMAC = 0;       		// Handle to our EMAC instance
volatile  uint   LinkStatus = 0; // Current link status 

Uint8  SrcMacID[ETH_ALEN] = {0x00,0x20,0x45,0x20,0x33,0x68};

Uint32  EmacRxNumtest=0;

int EmacInitial()
{
	Uint32 i;
	g_emacConfig.ModeFlags      = EMAC_CONFIG_MODEFLG_CHPRIORITY;
    g_emacConfig.MdioModeFlags  = MDIO_MODEFLG_AUTONEG;
    g_emacConfig.TxChannels     = 1;
	memcpy(g_emacConfig.MacAddr,SrcMacID,6);
    g_emacConfig.RxMaxPktPool   = 8;
    g_emacConfig.pfcbGetPacket  = &GetPacket;
    g_emacConfig.pfcbFreePacket = &FreePacket;
    g_emacConfig.pfcbRxPacket   = &RxPacket;
    g_emacConfig.pfcbStatus     = &StatusUpdate;
    g_emacConfig.pfcbStatistics = &StatisticsUpdate;
    
	InterruptInit();
	EMACControlModuleInit();
	MDIOInit();
	EMACModuleInit();
	
	// Initialize our buffer pool
    memset( &FreeQueue, 0, sizeof(PKTQ) );
    memset( &RxQueue, 0, sizeof(PKTQ) );
    
    // Init the buffer headers. Note that the 
    // buffer pointer and buffer length are fixed
    for( i=0; i<PKT_MAX; i++ )
    {
        memset( &packet_header[i], 0, sizeof(EMAC_Pkt) );
        packet_header[i].pDataBuffer = packet_buffer[i];
        packet_header[i].BufferLen   = 1518;
        pqPush( &FreeQueue, &packet_header[i] );
    }


    // Open EMAC instance 
    if(EMAC_open( 1, (Handle)0x12345678, &g_emacConfig, &hEMAC ))
   	{
       	return -1;
    }
    
    // Set the receive filter
    // 只接收发给本机的网络包
    if(EMAC_setReceiveFilter( hEMAC, EMAC_RXFILTER_BROADCAST))
    {
        return -1;
    }
	
	return 1;	
}


void EMACControlModuleInit()
{
	Uint32 i;
	Uint32 tmpVal;
	// Globally disable EMAC/MDIO interrupts in wrapper and 
	// put both EMAC and MDIO modules into reset
	EMAC_RSET( EWCTL, EMAC_FMKS( EWCTL, INTEN, DISABLE ) |
					 	EMAC_FMKS( EWCTL, EMACRST, YES ) |
					 	EMAC_FMKS( EWCTL, MDIORST, YES ) );
					 	
	// Wait ablout 100 cycles
	for( i=0; i<5; i++ )
	{
		tmpVal = EMAC_RGET( EWCTL );
	}
	
	// Leave EMAC/MDIO interrupts disabled and take both
	// EMAC and MDIO modules out of reset
	EMAC_RSET( EWCTL, EMAC_FMKS( EWCTL, INTEN, DISABLE ) |
					 	EMAC_FMKS( EWCTL, EMACRST, NO ) |
					 	EMAC_FMKS( EWCTL, MDIORST, NO ) );
					 	
	// Wait ablout 100 cycles
	for( i=0; i<5; i++ )
	{
		tmpVal = EMAC_RGET( EWCTL );
	}
	
	// Set EMAC Priority to "2" ,allocation regs "3"
	EMAC_RSET( EWTRCTRL, 0x23 );
	
	// Set Interrupt Timer Count (CPUclk/4)
	EMAC_RSET( EWINTTCNT, 1500 );
	
	// Enable global interrupt in wrapper
	EMAC_FSETS( EWCTL, INTEN, ENABLE );
					  
	return;
	
}

void MDIOInit()
{
#define PCLK 5
	MDIO_RSET( CONTROL, MDIO_FMKS( CONTROL, ENABLE, YES ) |
						MDIO_FMK( CONTROL, CLKDIV, PCLK ) |
						MDIO_FMKS( CONTROL, PREAMBLE, DISABLED));
	
	return;
}

void EMACModuleInit()
{
	volatile Uint32 *pRegAddr;
	Uint32 i;
	Uint32 tmpVal = 0;
	
	//Disable transmit,receive and clear MACCCONTROL
	EMAC_FSETS( TXCONTROL, TXEN, DISABLE );
	EMAC_FSETS( RXCONTROL, RXEN, DISABLE );
	EMAC_RSET( MACCONTROL, 0 );
	
	// MUST manually init TXnHDPs to NULL 
	pRegAddr = EMAC_ADDR( TX0HDP );
	for( i=0; i<8; i++ )
	{
		*pRegAddr++ = 0;
	}
	// MUST manually init RXnHDPs to NULL 
	pRegAddr = EMAC_ADDR( RX0HDP );
	for( i=0; i<8; i++ )
	{
		*pRegAddr++ = 0;
	}
	
	// 初始化统计寄存器
	pRegAddr = EMAC_ADDR( RXGOODFRAMES );
	for( i=0; i<36; i++ )
	{
		*pRegAddr++ = 0;
	}

	//初始化MAC地址  00 01 02 03 04 05
	//每个通道都初始化
	pRegAddr = EMAC_ADDR( MACADDRL0 );
	for( i=0; i<8; i++ )
	{
		*pRegAddr++ = g_emacConfig.MacAddr[5];
	}
	EMAC_RSET( MACADDRM, g_emacConfig.MacAddr[4] );
	
	for( i=3; i>0; i--)
	{
		tmpVal = ( tmpVal<<8 ) | g_emacConfig.MacAddr[i];
	}
	
	EMAC_RSET( MACADDRH, tmpVal );
	
	// Buffer offset always be zero
	EMAC_RSET( RXBUFFEROFFSET, 0 );
	
	// Clear Unicast receive on channel 0-7
	EMAC_RSET( RXUNICASTCLEAR, 0xFF );
	
	// Reset receive MBP enable register
	EMAC_RSET( RXMBPENABLE, 0 );

	
	// Enable transmit channel and receive channel interrupts
	EMAC_RSET( TXINTMASKCLEAR, 0xFF );
	EMAC_RSET( TXINTMASKSET , 1<<0 );
	EMAC_RSET( RXINTMASKCLEAR, 0xFF );
	EMAC_RSET( RXINTMASKSET , 1<<0 );
	
	// Enable transmit
	EMAC_FSETS( TXCONTROL, TXEN, ENABLE );
	
	// Enable receive
	EMAC_FSETS( RXCONTROL, RXEN, ENABLE );

	//Enable global interrupt in control module
	EMAC_FSETS( EWCTL, INTEN, ENABLE );

	return;
}



void InterruptInit()
{
	IRQ_globalDisable();
    IRQ_setVecs(vectors);
   	IRQ_map(IRQ_EVT_MACINT, 6);
   	IRQ_resetAll();
    IRQ_nmiEnable();
   	IRQ_enable(IRQ_EVT_MACINT);  //使能EMAC中断
    IRQ_globalEnable();
	
	return;
	
}
/*
 *----------GetPacket - Get empty packet for RX-------------
 *
 * This function is called from the EMAC module to get an
 * empty packet buffer. It returns a packet buffer to the
 * EMAC or returns NULL if there are no buffers available.
 */
EMAC_Pkt *GetPacket( Handle hApplication )
{
    EMAC_Pkt *pPkt;

    // Verify if handle came back OK. It is not used in this example
    if( (Uint32)hApplication != 0x12345678 )
    {
        return(0);
    }

    // Pop a packet off our local free queue
    pPkt = pqPop(&FreeQueue);

    if( pPkt )
    {
        // Tell the EMAC what offset to use by setting the DataOffset field
        // in the packet.
        pPkt->DataOffset = 0;
    }

    return( pPkt );
}


/*
 * FreePacket - Free packet that originated from TX or GetPacket().
 *
 * This function is called from the EMAC module to free a
 * packet buffer after a TX operation (or RX in the case of
 * a RX shutdown).
 *
 */
void FreePacket( Handle hApplication, EMAC_Pkt *pPKT )
{
    // Verify if handle came back OK. It is not used in this example
    if( (Uint32)hApplication != 0x12345678 )
    {
        return;
    }
    
    pqPush( &FreeQueue, pPKT );
}


/*
 * RxPacket - Reveived packet from the Network.
 *
 * This function is called by the EMAC to indicate a receive.
 * It just pushes the packet our receive queue.
 *
 * This function returns a free packet to replace the RX packet on
 * the EMAC queue. If there are no free packets available, it
 * returns NULL.
 */
EMAC_Pkt *RxPacket( Handle hApplication, EMAC_Pkt *pPKT )
{
    // Verify if handle came back OK. It is not used in this example
    if( (Uint32)hApplication != 0x12345678 )
    {
        return(0);
    }
    net_handle((pPKT->pDataBuffer+pPKT->DataOffset),pPKT->ValidLen);
    
    pqPush( &FreeQueue, pPKT );
    
    return( GetPacket(hApplication) );
}


int Emac_Send(struct sk_buff *skb)
{
    int i;
    
    if(skb->pPkt==0)
    {
        return -1;
    } 
    skb->pPkt->Flags      = EMAC_PKT_FLAGS_SOP | EMAC_PKT_FLAGS_EOP ;
    skb->pPkt->ValidLen   = skb->len;
    skb->pPkt->DataOffset = 0;
    skb->pPkt->PktChannel = 0;
    skb->pPkt->PktLength  = skb->len;
    skb->pPkt->PktFrags   = 1;
    
    // Must mask DSP mapped EMAC ISR when calling EMAC functions
    IRQ_disable( IRQ_EVT_MACINT );
    i = EMAC_sendPacket( hEMAC, skb->pPkt );
	IRQ_enable( IRQ_EVT_MACINT );
	
	if(i!=0)
	{
	   return -1;
	}
    
    return 0;
}

int Emac_Get_Addr(unsigned char *addr)
{
    memcpy(addr, SrcMacID, ETH_ALEN);  
    return 0;
}

char *LinkStr[] = { "No Link", 
					"10Mb/s Half Duplex", 
					"10Mb/s Full Duplex",
                    "100Mb/s Half Duplex", 
                    "100Mb/s Full Duplex" };

// StatusUpdate - The EMAC or MDIO status has changed
 void StatusUpdate( Handle hApplication )
{
    uint        retval;
    EMAC_Status status;

    /* Verify if handle came back OK. It is not used in this example */
    if( (Uint32)hApplication != 0x12345678 )
    {
        return;
    }

    /*
     * The status update function is called for several reasons, including
     * LINK change events and EMAC errors. Get the current status and print
     * it out. Don't start sending packets until there is a good link.
     *
     * NOTE: Call back into the EMAC is used without any reentrancy concerns.
     *       This because we are a callback function currently that was called
     *       from EMAC. Thus the reentrancy protection is still active!
     */
    retval = EMAC_getStatus( hEMAC, &status );

   
    LinkStatus = status.MdioLinkStatus;
}


// StatisticsUpdate - The EMAC statistics are in danger of overflow
void StatisticsUpdate( Handle hApplication )
{
    /* Verify if handle came back OK. It is not used in this example */
    if( (Uint32)hApplication != 0x12345678 )
    {
        return;
    }

    /*
     * Here call the EMAC_getStatistics() function and pass them to whoever
     * needing statistics information. This example doesn't have anything to
     * do with it so nothing is called here.
    */
}


// Pop a desc buffer off a queue
EMAC_Pkt *pqPop( PKTQ *pq )
{
    EMAC_Pkt *pPktHdr;
	
	IRQ_disable( IRQ_EVT_MACINT );
	   
    pPktHdr = pq->pHead;

    if( pPktHdr )
    {
        pq->pHead = pPktHdr->pNext;
        pq->Count--;
    }
    pPktHdr->pPrev = pPktHdr->pNext = 0;

	IRQ_enable( IRQ_EVT_MACINT );
	
    return( pPktHdr );
}


// Push a desc buffer onto a queue
void pqPush( PKTQ *pq, EMAC_Pkt *pPktHdr )
{
    
    IRQ_disable( IRQ_EVT_MACINT );
    
    pPktHdr->pNext = 0;

    if( !pq->pHead )
    {
        // Queue is empty - Initialize it with this one packet
        pq->pHead = pPktHdr;
        pq->pTail = pPktHdr;
    }
    else
    {
        // Queue is not empty - Push onto END
        pq->pTail->pNext = pPktHdr;
        pq->pTail        = pPktHdr;
    }
    pq->Count++;
    
    IRQ_enable( IRQ_EVT_MACINT );

    return;
}


⌨️ 快捷键说明

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