#define TESTAPP_GEN /****************************************************************************** * * Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * Except as contained in this notice, the name of the Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * ******************************************************************************/ /** * * @file xaxiethernet_example_polled.c * * Implements examples that utilize the Axi Ethernet's FIFO direct frame transfer * mode in a polled fashion to send and receive frames. * * These examples demonstrate: * * - How to perform simple polling send and receive. * - Advanced frame processing * - Error handling * * Functional guide to example: * * - AxiEthernetSingleFramePolledExample() demonstrates the simplest way to send * and receive frames in polled mode. * * - AxiEthernetMultipleFramesPolledExample() demonstrates how to transmit a * "burst" of frames by queueing up several in the packet FIFO prior to * transmission. * * - AxiEthernetPollForTxStatus() demonstrates how to poll for transmit complete * status and how to handle error conditions. * * - AxiEthernetPollForRxStatus() demonstrates how to poll for receive status and * how to handle error conditions. * * - AxiEthernetResetDevice() demonstrates how to reset the driver/HW without * losing all configuration settings. * * Note that the advanced frame processing algorithms shown here are not limited * to polled mode operation. The same techniques can be used for FIFO direct * interrupt driven mode as well. * *
* MODIFICATION HISTORY:
*
* Ver   Who  Date     Changes
* ----- ---- -------- -------------------------------------------------------
* 1.00a asa  4/30/10 First release based on the ll temac driver
*
* 
* ******************************************************************************/ /***************************** Include Files *********************************/ #include "xaxiethernet_example.h" #include "xllfifo.h" #include "xil_cache.h" #ifdef XPAR_XUARTNS550_NUM_INSTANCES #include "xuartns550_l.h" #endif /************************** Constant Definitions ****************************/ /* * The following constants map to the XPAR parameters created in the * xparameters.h file. They are defined here such that a user can easily * change all the needed parameters in one place. */ #ifndef TESTAPP_GEN #define AXIETHERNET_DEVICE_ID XPAR_AXIETHERNET_0_DEVICE_ID #define FIFO_DEVICE_ID XPAR_AXI_FIFO_0_DEVICE_ID #endif /************************** Variable Definitions ****************************/ EthernetFrame TxFrame; /* Transmit frame buffer */ EthernetFrame RxFrame; /* Receive frame buffer */ XAxiEthernet AxiEthernetInstance; XLlFifo FifoInstance; /************************** Function Prototypes *****************************/ int AxiEthernetPolledExample(u16 AxiEthernetDeviceId, u16 FifoDeviceId); int AxiEthernetSingleFramePolledExample(); int AxiEthernetMultipleFramesPolledExample(); int AxiEthernetPollForTxStatus(); int AxiEthernetPollForRxStatus(); int AxiEthernetResetDevice(); /*****************************************************************************/ /** * * This is the main function for the AxiEthernet example. This function is not * included if the example is generated from the TestAppGen test tool. * * @param None. * * @return -XST_SUCCESS to indicate success * -XST_FAILURE to indicate failure * * * @note None. * ****************************************************************************/ #ifndef TESTAPP_GEN int main(void) { int Status; #ifdef XPAR_XUARTNS550_NUM_INSTANCES XUartNs550_SetBaud(STDIN_BASEADDRESS, XPAR_XUARTNS550_CLOCK_HZ, 9600); XUartNs550_SetLineControlReg(STDIN_BASEADDRESS, XUN_LCR_8_DATA_BITS); #endif #if XPAR_MICROBLAZE_USE_ICACHE Xil_ICacheInvalidate(); Xil_ICacheEnable(); #endif #if XPAR_MICROBLAZE_USE_DCACHE Xil_DCacheInvalidate(); Xil_DCacheEnable(); #endif AxiEthernetUtilErrorTrap("\r\n--- Enter main() ---"); AxiEthernetUtilErrorTrap("This test may take several minutes to finish"); /* * Call the AxiEthernet polled example , specify the Device ID * generated in xparameters.h */ Status = AxiEthernetPolledExample(AXIETHERNET_DEVICE_ID, FIFO_DEVICE_ID); if (Status != XST_SUCCESS) { AxiEthernetUtilErrorTrap("Failed test poll mode fifo"); return XST_FAILURE; } AxiEthernetUtilErrorTrap("Test passed"); AxiEthernetUtilErrorTrap("--- Exiting main() ---"); return XST_SUCCESS; } #endif /*****************************************************************************/ /** * * This function demonstrates the usage of the Axi Ethernet by sending and * receiving frames in polled mode. * * * @param AxiEthernetDeviceId is device ID of the AxiEthernet Device , * typically XPAR__DEVICE_ID value from * xparameters.h * @param FifoDeviceId is device ID of the Fifo device taken from * xparameters.h * * @return -XST_SUCCESS to indicate success * -XST_FAILURE to indicate failure * * @note AxiFifo hardware must be initialized before initializing * AxiEthernet. Since AxiFifo reset line is connected to the * AxiEthernet reset line, a reset of AxiFifo hardware during its * initialization would reset AxiEthernet. * ******************************************************************************/ int AxiEthernetPolledExample(u16 AxiEthernetDeviceId, u16 FifoDeviceId) { int Status; XAxiEthernet_Config *MacCfgPtr; int LoopbackSpeed; /*************************************/ /* Setup device for first-time usage */ /*************************************/ /* * Get the configuration of AxiEthernet hardware. */ MacCfgPtr = XAxiEthernet_LookupConfig(AxiEthernetDeviceId); /* * Check whether AXIFIFO is present or not */ if(MacCfgPtr->AxiDevType != XPAR_AXI_FIFO) { AxiEthernetUtilErrorTrap ("Device HW not configured for FIFO mode\r\n"); return XST_FAILURE; } /* * Initialize AXIFIFO hardware. AXIFIFO must be initialized before * AxiEthernet. During AXIFIFO initialization, AXIFIFO hardware is * reset, and since AXIFIFO reset line is connected to AxiEthernet, * this would ensure a reset of AxiEthernet. */ XLlFifo_Initialize(&FifoInstance, MacCfgPtr->AxiDevBaseAddress); /* * Initialize AxiEthernet hardware. */ Status = XAxiEthernet_CfgInitialize(&AxiEthernetInstance, MacCfgPtr, MacCfgPtr->BaseAddress); if (Status != XST_SUCCESS) { AxiEthernetUtilErrorTrap("Error in initialize"); return XST_FAILURE; } /* * Set the MAC address */ Status = XAxiEthernet_SetMacAddress(&AxiEthernetInstance, (u8 *) AxiEthernetMAC); if (Status != XST_SUCCESS) { AxiEthernetUtilErrorTrap("Error setting MAC address"); return XST_FAILURE; } /* * Set PHY to loopback, speed depends on phy type. * MII is 100 and all others are 1000. */ if (XAxiEthernet_GetPhysicalInterface(&AxiEthernetInstance) == XAE_PHY_TYPE_MII) { LoopbackSpeed = AXIETHERNET_LOOPBACK_SPEED; } else { LoopbackSpeed = AXIETHERNET_LOOPBACK_SPEED_1G; } Status = AxiEthernetUtilEnterLoopback(&AxiEthernetInstance, LoopbackSpeed); if (Status != XST_SUCCESS) { AxiEthernetUtilErrorTrap("Error setting the PHY loopback"); return XST_FAILURE; } /* * Set PHY<-->MAC data clock */ Status = XAxiEthernet_SetOperatingSpeed(&AxiEthernetInstance, (u16)LoopbackSpeed); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Setting the operating speed of the MAC needs a delay. There * doesn't seem to be register to poll, so please consider this * during your application design. */ AxiEthernetUtilPhyDelay(2); /****************************/ /* Run through the examples */ /****************************/ /* * Run the Single Frame polled example */ Status = AxiEthernetSingleFramePolledExample(); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Run the Multiple Frames polled example */ Status = AxiEthernetMultipleFramesPolledExample(); if (Status != XST_SUCCESS) { return XST_FAILURE; } return XST_SUCCESS; } /*****************************************************************************/ /** * * This function demonstrates the usage of the Axi Ethernet by sending and * receiving a single frame in polled mode. * * @param None. * * @return -XST_SUCCESS to indicate success * -XST_FAILURE to indicate failure * * @note None. * ******************************************************************************/ int AxiEthernetSingleFramePolledExample(void) { u32 FifoFreeBytes; int PayloadSize = 100; u32 TxFrameLength; u32 RxFrameLength; /* * Start the Axi Ethernet device */ XAxiEthernet_Start(&AxiEthernetInstance); /* * Setup the packet to be transmitted */ AxiEthernetUtilFrameHdrFormatMAC(&TxFrame, AxiEthernetMAC); AxiEthernetUtilFrameHdrFormatType(&TxFrame, PayloadSize); AxiEthernetUtilFrameSetPayloadData(&TxFrame, PayloadSize); /* * Clear out the receive packet memory area */ AxiEthernetUtilFrameMemClear(&RxFrame); /* * Calculate frame length (not including FCS) */ TxFrameLength = XAE_HDR_SIZE + PayloadSize; /*******************/ /* Send the packet */ /*******************/ /* * Wait for enough room in FIFO to become available */ do { FifoFreeBytes = XLlFifo_TxVacancy(&FifoInstance); } while (FifoFreeBytes < TxFrameLength); /* * Write the frame data to FIFO */ XLlFifo_Write(&FifoInstance, TxFrame, TxFrameLength); /* * Initiate transmit */ XLlFifo_TxSetLen(&FifoInstance, TxFrameLength); /* * Wait for status of the transmitted packet */ switch (AxiEthernetPollForTxStatus()) { case XST_SUCCESS:/* Got a sucessfull transmit status */ break; case XST_NO_DATA: /* Timed out */ AxiEthernetUtilErrorTrap("Tx timeout"); return XST_FAILURE; default: /* Some other error */ return XST_FAILURE; } /**********************/ /* Receive the packet */ /**********************/ /* * Wait for packet Rx */ switch (AxiEthernetPollForRxStatus()) { case XST_SUCCESS:/* Got a sucessfull receive status */ break; case XST_NO_DATA: /* Timed out */ AxiEthernetUtilErrorTrap("Rx timeout"); return XST_FAILURE; default: /* Some other error */ return XST_FAILURE; } while(XLlFifo_RxOccupancy(&FifoInstance)) { /* * A packet as arrived, get its length */ RxFrameLength = XLlFifo_RxGetLen(&FifoInstance); /* * Read the received packet data */ XLlFifo_Read(&FifoInstance, &RxFrame, RxFrameLength); /* * Verify the received frame length */ if ((RxFrameLength) != TxFrameLength) { AxiEthernetUtilErrorTrap("Receive length incorrect"); return XST_FAILURE; } /* * Validate frame data */ if (AxiEthernetUtilFrameVerify(&TxFrame, &RxFrame) != 0) { AxiEthernetUtilErrorTrap("Receive Data mismatch"); return XST_FAILURE; } } /* * Stop device */ XAxiEthernet_Stop(&AxiEthernetInstance); return XST_SUCCESS; } /*****************************************************************************/ /** * * This example uses polled mode to queue up multiple frames in the packet * FIFOs before sending them in a single burst. Receive packets are handled in * a similar way. * * @param None. * * @return -XST_SUCCESS to indicate success * -XST_FAILURE to indicate failure * * @note None. * ******************************************************************************/ int AxiEthernetMultipleFramesPolledExample(void) { u32 FramesToLoopback; u32 PayloadSize; u32 TxFrameLength; u32 RxFrameLength; u32 FifoFreeBytes; u32 Index; /* * Start the Axi Ethernet device */ XAxiEthernet_Start(&AxiEthernetInstance); /* * Setup the number of frames to loopback (FramesToLoopback) and the * size of the frame (PayloadSize) to loopback. The default settings * should work for every case. Modifying the settings can cause * problems, see discussion below: * * If PayloadSize is set small and FramesToLoopback high, then it is * possible to cause the transmit status FIFO to overflow. * * If PayloadSize is set large and FramesToLoopback high, then it is * possible to cause the transmit packet FIFO to overflow. * * Either of these scenarios may be worth trying out to observe how * the driver reacts. The exact values to cause these types of errors * will vary due to the sizes of the FIFOs selected at hardware build * time. But the following settings should create problems for all * FIFO sizes: * * Transmit status FIFO overflow * PayloadSize = 1 * FramesToLoopback = 1000 * * Transmit packet FIFO overflow * PayloadSize = 1500 * FramesToLoopback = 16 * * These values should always work without error * PayloadSize = 100 * FramesToLoopback = 5 */ PayloadSize = 100; FramesToLoopback = 5; /* * Calculate Tx frame length (not including FCS) */ TxFrameLength = XAE_HDR_SIZE + PayloadSize; /* * Setup the packet to be transmitted */ AxiEthernetUtilFrameHdrFormatMAC(&TxFrame, AxiEthernetMAC); AxiEthernetUtilFrameHdrFormatType(&TxFrame, PayloadSize); AxiEthernetUtilFrameSetPayloadData(&TxFrame, PayloadSize); /****************/ /* Send packets */ /****************/ /* * Since we may be interested to see what happens when FIFOs overflow, * don't check for room in the transmit packet FIFO prior to writing * to it. */ /* * Write frame data to FIFO * Fifo core only allows loading and sending one frame at a time. */ for (Index = 0; Index < FramesToLoopback; Index++) { /* Make sure there is room in the FIFO */ do { FifoFreeBytes = XLlFifo_TxVacancy(&FifoInstance); } while (FifoFreeBytes < TxFrameLength); XLlFifo_Write(&FifoInstance, TxFrame, TxFrameLength); XLlFifo_TxSetLen(&FifoInstance, TxFrameLength); switch (AxiEthernetPollForTxStatus()) { case XST_SUCCESS: /* Got a sucessfull transmit status */ break; case XST_NO_DATA: /* Timed out */ AxiEthernetUtilErrorTrap("Tx timeout"); return XST_FAILURE; break; default: /* Some other error */ AxiEthernetResetDevice(); return XST_FAILURE; } } /**********************/ /* Receive the packet */ /**********************/ /* * Wait for the packets to arrive * The Fifo core only allows us to pull out one frame at a time. */ for (Index = 0; Index < FramesToLoopback; ) { /* * Wait for packet Rx */ switch (AxiEthernetPollForRxStatus()) { case XST_SUCCESS: /* Got a successfull receive status */ break; case XST_NO_DATA: /* Timed out */ AxiEthernetUtilErrorTrap("Rx timeout"); return XST_FAILURE; break; default: /* Some other error */ AxiEthernetResetDevice(); return XST_FAILURE; } while(XLlFifo_RxOccupancy(&FifoInstance)) { /* * A packet has arrived, get its length */ RxFrameLength = XLlFifo_RxGetLen(&FifoInstance); /* * Verify the received frame length */ if ((RxFrameLength) != TxFrameLength) { AxiEthernetUtilErrorTrap("Receive length incorrect"); return XST_FAILURE; } /* * Read the received packet data */ XLlFifo_Read(&FifoInstance, &RxFrame, RxFrameLength); if (AxiEthernetUtilFrameVerify (&TxFrame, &RxFrame) != 0) { AxiEthernetUtilErrorTrap("Receive Data Mismatch"); return XST_FAILURE; } Index++; } } /* * Stop device */ XAxiEthernet_Stop(&AxiEthernetInstance); return XST_SUCCESS; } /******************************************************************************/ /** * This functions polls the Tx status and waits for an indication that a frame * has been transmitted successfully or a transmit related error has occurred. * If an error is reported, it handles all the possible error conditions. * * @param None. * * @return - XST_SUCCESS, Tx has completed * - XST_NO_DATA, Timeout. Tx failure. * - XST_FIFO_ERROR, Error in the FIFO. * * @note None. * ******************************************************************************/ int AxiEthernetPollForTxStatus(void) { int Status = XST_NO_DATA; int Attempts = 100000; /* * Number of attempts to get status before * giving up */ /* * Wait for transmit complete indication */ do { if (--Attempts <= 0) break; /* Give up? */ if (XLlFifo_Status(&FifoInstance) & XLLF_INT_TC_MASK) { XLlFifo_IntClear(&FifoInstance, XLLF_INT_TC_MASK); Status = XST_SUCCESS; } if (XLlFifo_Status(&FifoInstance) & XLLF_INT_ERROR_MASK) { Status = XST_FIFO_ERROR; } } while (Status == XST_NO_DATA); switch (Status) { case XST_SUCCESS: /* Frame sent without error */ case XST_NO_DATA: /* Timeout */ break; case XST_FIFO_ERROR: AxiEthernetUtilErrorTrap("FIFO error"); AxiEthernetResetDevice(); break; default: AxiEthernetUtilErrorTrap("Driver returned unknown transmit status"); break; } return (Status); } /******************************************************************************/ /** * This functions polls the Rx status and waits for an indication that a frame * has arrived or a receive related error has occurred. If an error is reported, * handle all the possible error conditions. * * @param None. * * @return - XST_SUCCESS, a frame has been received * - XST_NO_DATA, Timeout. Rx failure. * - XST_FIFO_ERROR, Error in the FIFO. * - XST_DATA_LOST, a frame has been dropped * * @note None. * ******************************************************************************/ int AxiEthernetPollForRxStatus(void) { int Status = XST_NO_DATA; int Attempts = 1000000; /* Number of times to get a status before * giving up */ /* * There are two ways to poll for a received frame: * * XAxiEthernet_Recv() can be used and repeatedly called until it * returns a length, but this method does not provide any error * detection. * * XAxiEthernet_FifoQueryRecvStatus() can be used and this function * provides more information to handle error conditions. */ /* * Wait for something to happen */ do { if (--Attempts <= 0) break; /* Give up? */ if (XLlFifo_Status(&FifoInstance) & XLLF_INT_RC_MASK) { Status = XST_SUCCESS; } if (XLlFifo_Status(&FifoInstance) & XLLF_INT_ERROR_MASK) { Status = XST_FIFO_ERROR; } if (XAxiEthernet_GetIntStatus(&AxiEthernetInstance) & XAE_INT_RXRJECT_MASK) { Status = XST_DATA_LOST; } /* When the RXFIFOOVR bit is set, the RXRJECT bit also * gets set */ if (XAxiEthernet_GetIntStatus(&AxiEthernetInstance) & XAE_INT_RXFIFOOVR_MASK) { Status = XST_DATA_LOST; } } while (Status == XST_NO_DATA); switch (Status) { case XST_SUCCESS: /* Frame has arrived */ case XST_NO_DATA: /* Timeout */ break; case XST_DATA_LOST: AxiEthernetUtilErrorTrap("Frame was dropped"); break; case XST_FIFO_ERROR: AxiEthernetUtilErrorTrap("FIFO error"); AxiEthernetResetDevice(); break; default: AxiEthernetUtilErrorTrap("Driver returned invalid transmit status"); break; } return (Status); } /******************************************************************************/ /** * This function resets the device but preserves the options set by the user. * * @param None. * * @return -XST_SUCCESS if reset is successful * -XST_FAILURE. if reset is not successful * * @note None. * ******************************************************************************/ int AxiEthernetResetDevice(void) { int Status; u8 MacSave[6]; u32 Options; /* * Stop device */ XAxiEthernet_Stop(&AxiEthernetInstance); /* * Save the device state */ XAxiEthernet_GetMacAddress(&AxiEthernetInstance, MacSave); Options = XAxiEthernet_GetOptions(&AxiEthernetInstance); /* * Stop and reset both the fifo and the AxiEthernet the devices */ XLlFifo_Reset(&FifoInstance); XAxiEthernet_Reset(&AxiEthernetInstance); /* * Restore the state */ Status = XAxiEthernet_SetMacAddress(&AxiEthernetInstance, MacSave); Status |= XAxiEthernet_SetOptions(&AxiEthernetInstance, Options); Status |= XAxiEthernet_ClearOptions(&AxiEthernetInstance, ~Options); if (Status != XST_SUCCESS) { AxiEthernetUtilErrorTrap("Error restoring state after reset"); return XST_FAILURE; } return XST_SUCCESS; }