embeddedsw/XilinxProcessorIPLib/drivers/axiethernet/examples/xaxiethernet_example_polled.c
Jagannadha Sutradharudu Teki 2c8f92039d embeddesw: Add initial code support
Added initial support Xilinx Embedded Software.

Signed-off-by: Jagannadha Sutradharudu Teki <jaganna@xilinx.com>
2014-06-24 16:45:01 +05:30

806 lines
21 KiB
C
Executable file

/******************************************************************************
*
* 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.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -------------------------------------------------------
* 1.00a asa 4/30/10 First release based on the ll temac driver
*
* </pre>
*
******************************************************************************/
/***************************** 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_<AXIETHERNET_instance>_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;
}