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

📄 emac_local_loopback_example.c

📁 dsp tms320c6486的csl例程
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  ============================================================================
 *   Copyright (c) Texas Instruments Inc 2002, 2003, 2004, 2005, 2006
 *
 *   Use of this software is controlled by the terms and conditions found in the
 *   license agreement under which this software has been supplied.
 *   ===========================================================================
 */

/* ============================================================================
 *   @file  Emac_example.c
 *
 *   PATH:  \$(CSLPATH)\\example\\emac\\src
 *
 *   @brief  Example for EMAC CSL
 *
 *  ============================================================================
 *   @n Target Platform: TCI6486 on Quick Turn
 *  ============================================================================
 *   @n <b> Example Description </b>
 *   @n This example, is a simple loop back configured for core 0. If emac is configured
 *      no need to configure ECTL, EMAC src configures it. Here the EMAC src configures 
 *      interrupts for single core i.e core 0, one Rx channel and one Tx channel.
 *      This example tested for core 0 for 100 packets.
 *
 *  This example can be configured to test it on core 1 and core2 as well.
 *  Please do the below  changes
 *      if user wants to dedicate receive channel 1 for core 1, he has to select
 *      core 0 channels as dummy and do not send any packet on this channel
 *      i.e configuration would be 
 *      ecfg.ChannelInfo[0].TxChannels = 1;
 *    	ecfg.ChannelInfo[0].RxChannels = 1;
 *      ecfg.ChannelInfo[1].TxChannels = 1;
 *      ecfg.ChannelInfo[1].RxChannels = 1;
 *      ecfg.ChannelInfo[2].TxChannels = 0;
 *      ecfg.ChannelInfo[2].RxChannels = 0;
 *
 *      otherwise it selects receive channel 0 as default.
 *
 *      if user wants to dedicate receive channel 2 for core 2, he has to select
 *      core 0 and core 1channels as dummy and do not send any packet on these channels
 *      i.e configuration would be 
 *      ecfg.ChannelInfo[0].TxChannels = 1;
 *    	ecfg.ChannelInfo[0].RxChannels = 1;
 *      ecfg.ChannelInfo[1].TxChannels = 1;
 *      ecfg.ChannelInfo[1].RxChannels = 1;
 *      ecfg.ChannelInfo[2].TxChannels = 1;
 *      ecfg.ChannelInfo[2].RxChannels = 1;
 *
 *      otherwise it selects receive channel 0 as default.
 *
 *      Note: Since it(C6486) is a six core divice, there is a separeate MAC address
 *      for each core. While doing configuration for other cores pass the specific
 *      core MAC address through MacAddr[6][6] 2-D array, a member of EMAC_Config structure.  
 *      
 *      Choose TX packet channel accordingly while preparing the packet to send
 *      i.e pPkt->PktChannel = 0 (for core 0), 1 (for core 1), 2 (for core 2) in this example;
 *       
 *      Change the second argument(coreNum 0, 1 and 2 respectively for core 0, 1 and 2)in below functions
 *       EMAC_RxServiceCheck(hEMAC, coreNum)
 *       EMAC_TxServiceCheck(hEMAC, coreNum)
 *       EMAC_timerTick(hEMAC, coreNum)
 *   
 *  Please also ensure that proper Linker command file is used
 *      i.e use specific core global memory map for L2 (L2_GLOBAL in cmd file should be changed accordingly)
 *  
 *      LOCAL_LOOPBACK performs loopback in the MAC, however since this example
 *      also does not check for a LINK on the physical PHY as it does not configire MDIO.      
 *
 * Note: This same example works for instance "one" also but with some changes listed
 *       1. Use corresponding rx and tx interrupt event IDs to hook up the interrupts
 *       2. While calling EMAC_Open, pass the instance number as 1.
 *       3. Enable PSC for EMAC instance 1
 *       4. And to work on mutli core the above said procedure can be followed
 *
 *
 * =============================================================================
 *
 *   <b> Procedure to run the example </b>
 *   @verbatim
 *      1. Configure the CCS setup to work with.
 *      2. Launch CCS window.
 *      3. Open project Emac_local_loopback_example.pjt
 *      4. Build the project and load the .out file of the project.
 *      5. Run the example.
 *   @endverbatim
 *
 */

#include <stdio.h>
#include <csl_emac.h>
#include <cslr_dev.h>

#define LOCAL_LOOPBACK  1       /* Loopback internal to the EMAC */
#define PHY_LOOPBACK    0       /* Loopback at the PHY device    */
#define QUICKTURN       1       /* Quickturn test */ 

/*
 * We'll use INT5 for the EMAC Rx and 6 for Tx- this is an arbitrary choice
 */
#define EMAC_INT_VAL    9
#define EMAC_INT_FLAG   (3<<EMAC_INT_VAL)

/*
 * Raw Data Buffers
 *
 * This example uses internal memory, so we could just use 1518 as our
 * buffer size. However, if the buffers were in cacheable external
 * memory, we'd have to make sure each was cache aligned, and
 * thus use a size of at least 1536 because a buffer must fill an
 * the entire cache line.
 */
#define PKT_MAX 32

#pragma DATA_SECTION(packet_header, ".src_buff");
EMAC_Pkt packet_header[PKT_MAX];
#pragma DATA_SECTION(packet_buffer, ".src_buff");
Uint8 packet_buffer[PKT_MAX][1536];
#pragma DATA_SECTION(packet_sourcedata, ".src_buff");
Uint8 packet_sourcedata[1536];

/*
 * Packet Queue
 *
 * This simple queue object is just for our example packet
 * queue. It is not requried for using EMAC/MDIO
 *
 */
typedef struct app_pktq {
  Uint32            Count;      /**< Number of packets in queue */
  EMAC_Pkt          *pHead;     /**< Pointer to first packet    */
  EMAC_Pkt          *pTail;     /**< Pointer to last packet     */
} APP_PKTQ;

/*
 * Queue Helper Functions
 */
static EMAC_Pkt *App_pqPop( APP_PKTQ *pq );
static void App_pqPush( APP_PKTQ *pq, EMAC_Pkt *pPktHdr );

/*
 * Declare our packet queues
 */
APP_PKTQ     FreeQueue;             /* Free packets for RX or TX */
APP_PKTQ     RxQueue;               /* Received packets */

/*
 * Declare some local status variables
 */
Handle            hEMAC = 0;       /* Handle to our EMAC instance */
volatile Uint32   LinkStatus = 0;  /* Our current link status */
volatile Uint32   LocalTicks = 0;  /* Current time in 100ms ticks */

extern cregister volatile unsigned int IER;
#define OUREMAC_enter() IER &= ~EMAC_INT_FLAG
#define OUREMAC_exit()  IER |= EMAC_INT_FLAG


/*
 * Declare some local functions
 */
static EMAC_Pkt *GetPacket(Handle hApplication);
static void     FreePacket(Handle hApplication, EMAC_Pkt *pPKT);
static EMAC_Pkt *RxPacket( Handle hApplication, EMAC_Pkt *pPKT);
static void     StatusUpdate(Handle hApplication);
static void     StatisticsUpdate(Handle hApplication);
static int      verify_packet( EMAC_Pkt *pPkt, Uint32 size );

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


/*
 * Declare some external functions
 */
extern void DoTimerInitialization(void);
extern void DoInterruptsInitialization(void);
extern void DoInterruptEnd(void);


/*
 * =============================================================================
 *   @func   Main 
 *
 *   @desc
 *      Main Example Entry Point.  
 *      
 *   @arg
 *      None
 *      
 *   @expected result
 *      If the example passes, it displays the message "Example Passed"
 *      If the example fails, it displays the messae "Example Failed"
 *
 *   @eg
 *      exampleMain(); // Read description.
 * =============================================================================
 */
void main()
{
    EMAC_Config ecfg;
    Uint32      i, size, j;
    Uint32      TxCount=0;
	Uint32		RxCount=0;
	Uint32		count = (1514-60)+1;
    EMAC_Pkt    *pPkt;


	/* test less packets since quickturn is slow */
	if(QUICKTURN){
		count = (160-60);  // 100 packets
	}

    /*
     * Basic Initialization
     */                    
    printf("EMAC example\n");

    /* Init packet data array */
    for( i=0; i<1514; i++ ) {
		packet_sourcedata[i] = i;
	}

    /* Initialize our buffer pool */
    memset( &FreeQueue, 0, sizeof(APP_PKTQ) );
    memset( &RxQueue, 0, sizeof(APP_PKTQ) );
    for( i=0; i<PKT_MAX; i++ ) {
        /*
         * Init the buffer headers. Note that the buffer pointer
         * and buffer length are fixed and to not change
         */
        memset( &packet_header[i], 0, sizeof(EMAC_Pkt) );
        packet_header[i].pDataBuffer = packet_buffer[i];
        packet_header[i].BufferLen   = 1518;
        App_pqPush( &FreeQueue, &packet_header[i] );
    }

    /*
     * Inialize Configuration and Open EMAC
     */
    
    /* Not using the MDIO configuration */
	 ecfg.UseMdio = 0;

    /* Setup the EMAC configuration */
#if LOCAL_LOOPBACK
    ecfg.ModeFlags      = EMAC_CONFIG_MODEFLG_MACLOOPBACK | EMAC_CONFIG_MODEFLG_FULLDUPLEX;
#else
    ecfg.ModeFlags      = 0;
#endif
#if PHY_LOOPBACK
    ecfg.MdioModeFlags  = MDIO_MODEFLG_FD1000 | MDIO_MODEFLG_LOOPBACK;
#else
    ecfg.MdioModeFlags  = MDIO_MODEFLG_FD1000;
#endif
    ecfg.ChannelInfo[0].TxChannels = 1;
	ecfg.ChannelInfo[0].RxChannels = 1;

	for (i = 1; i < 6; i++) {
		ecfg.ChannelInfo[i].TxChannels = 0;
		ecfg.ChannelInfo[i].RxChannels = 0;
	}

    ecfg.RxMaxPktPool              = 8;
    ecfg.pfcbGetPacket             = &GetPacket;
    ecfg.pfcbFreePacket            = &FreePacket;
    ecfg.pfcbRxPacket              = &RxPacket;
    ecfg.pfcbStatus                = &StatusUpdate;
    ecfg.pfcbStatistics            = &StatisticsUpdate;

    /*
     * For this example we'll set our EMAC address to be 00:01:02:03:04:05
     * If this were a real driver, we'd have to read the EMAC
     * address from where it is stored in hardware (board dependent)
     */
	for (j=0; j<6; j++){
    	for (i=0; i<6; i++){
		    if (j==0)
        	ecfg.MacAddr[j][i] = i;
			else
			ecfg.MacAddr[j][i] = 0;
		}
	}
    /* Enable PSC for EMAC instance 0*/
	*(volatile unsigned int *)0x02ae0a1c = 0x03;

    /* Open EMAC instance 0 */
    printf("Calling EMAC_open()\n");
    i = EMAC_open( 1, (Handle)0x12345678, 0, &ecfg, &hEMAC );
    if(i)
    {
        printf("Returned error %08x\n",i);
        goto exit;
    }

    /* Set the receive filter */
    /* Use our re-entrancy gate to call EMAC functions */
    printf("Calling EMAC_setReceiveFilter()\n");
    OUREMAC_enter();
    i = EMAC_setReceiveFilter( hEMAC, EMAC_RXFILTER_DIRECT );
    OUREMAC_exit();
    if(i)
    {
        printf("Returned error %08x\n",i);
        goto close_emac;
    }

    /* Do timer intialization */
    DoTimerInitialization();

    /* Do interrupt setup */
	DoInterruptsInitialization();

    /*
     * Wait for the device to link
     *
     * The device can not send or receive packets until its
     * linked.
     *
     */
    printf("Waiting for link...\n");
    LocalTicks = 0;
	if(ecfg.UseMdio){
        while( !LinkStatus && LocalTicks < 100 );
   }

    /* Need to print this here, as it's not possible from the callback function */
    EMAC_getStatus( hEMAC, &status, 0);

    LinkStatus = status.MdioLinkStatus;
    if( LinkStatus <= 5 )
        printf("Link Status  : %s on PHY number %d\n",
               LinkStr[LinkStatus],status.PhyDev);

    printf("Packets Held : %d-RX  %d-TX\n",
           status.RxPktHeld, status.TxPktHeld);
    if( status.FatalError )
        printf("Fatal Error  : %d\n",status.FatalError);

    if( !LinkStatus )
        printf("\nWARNING: No device LINK.\n");

   /* Start the example */
    printf("\nStarting packet transfer...\n");

    LocalTicks = 0;
    while( RxCount<count ) {
        /* Check for timeout */
		if(!QUICKTURN){
	  	    if( LocalTicks > 50 ) {
	   	        printf("ERROR: Timeout waiting for TX/RX\n");
        	    break;
	   	    }
		}

        /* See if we should send a packet */
        if( TxCount<count && TxCount<(RxCount+8) ) {
            /*
             * Send a packet
            */

            /* First get a packet buffer from our private queue */
            pPkt = App_pqPop( &FreeQueue );
            if( pPkt ) {
                /* Fill buffer with a pattern, using "count+60" for size */
                size = TxCount + 60;
                memcpy( pPkt->pDataBuffer, packet_sourcedata, size);

                /* Send the packet */
                pPkt->Flags      = EMAC_PKT_FLAGS_SOP | EMAC_PKT_FLAGS_EOP;
                pPkt->ValidLen   = size;
                pPkt->DataOffset = 0;
                pPkt->PktChannel = 0;
                pPkt->PktLength  = size;
                pPkt->PktFrags   = 1;

                /*
                 * IMPORTANT: If our data packet were in EXTERNAL memory,
                 * we would have to clean it from the CACHE before submitting
                 * it to the EMAC module!!!
                 *
                 * We should probably do the clean operation right here.
                 */

                /* Use our re-entrancy gate to call EMAC functions */
                OUREMAC_enter();
                i = EMAC_sendPacket(hEMAC, pPkt);
                OUREMAC_exit();
                if(i) {
                    printf("EMAC_sendPacket() returned error %08x\n",i);
                    break;
                }

                /* Bump the TX count */
                TxCount++;
            }
        }

        /*
         * See if we received a packet
         */
        if( pPkt = App_pqPop( &RxQueue ) ) {
            /* Validate this packet */
            if( !verify_packet( pPkt, RxCount + 60 ) ) {
                printf("ERROR: Verify failure on packet %d\n",RxCount);
                break;
            }

            /* Free the packet */
            App_pqPush( &FreeQueue, pPkt );

            /* Bump the RX count */
            RxCount++;
        }
    }

    printf("Sent %d of %d packets, received %d packets\n",
            TxCount, count, RxCount);

    /*
     * Close EMAC
     */
close_emac:

    /* Since we're done, we leave the interrupt disabled */
    DoInterruptEnd();
  
    printf("Calling EMAC_close()\n");
    i = EMAC_close( hEMAC );
    hEMAC = 0;
    if(i) {
        printf("Returned error %08x\n",i);
        goto exit;
    }

exit:
    if( TxCount == count && RxCount == count )
        printf("\nExample Passed\n");
    else {
        printf("\nExample Failed\n");

⌨️ 快捷键说明

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