This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS/EK-TM4C1294XL: Tiva Ethernet MAC loopback code

Part Number: EK-TM4C1294XL


Tool/software: Code Composer Studio

I have implemented a simple MAC Loopback code for ethernet controller. This is for purposes of production diagnostics for a hardware product.

Although I have configured EMAC Conf egister with the appropriate bit set for Loopback mode and followed the Tivaware driver's manual for setting up DMA engine, I am not getting the Ethernet Interrupt. I have made the appropriate changes to start up code to reflect the correct function for Ethernet Interrupt Handling.

Also I am not sure how one can without assign a data buffer to the transmit and receive buffers which seem to be part of the stack which takes data assigned by tcpsend or receive instaed of us having to be able to assign a test packet to test integrity of MAC loopback.

#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_nvic.h"
#include "inc/hw_types.h"
#include "inc/hw_emac.h"
#include "driverlib/flash.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/sysctl.h"
#include "driverlib/systick.h"
#include "driverlib/timer.h"
#include "driverlib/rom.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom_map.h"
#include "driverlib/emac.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"
#include "utils/ustdlib.h"
#include "drivers/pinout.h"

//*****************************************************************************
//
// Defines for setting up the system clock.
//
//*****************************************************************************
#define SYSTICKHZ               CLOCK_CONF_SECOND
#define SYSTICKMS               (1000 / SYSTICKHZ)
#define SYSTICKUS               (1000000 / SYSTICKHZ)
#define SYSTICKNS               (1000000000 / SYSTICKHZ)

//*****************************************************************************/
//*****************************************************************************
//
// Ethernet DMA descriptors.
//
// The MAC hardware needs a minimum of 3 receive descriptors to operate. The
// number used will be application-dependent and should be tuned for best
// performance.
//
//*****************************************************************************
#define NUM_TX_DESCRIPTORS 3
#define NUM_RX_DESCRIPTORS 3
tEMACDMADescriptor g_psRxDescriptor[NUM_TX_DESCRIPTORS];
tEMACDMADescriptor g_psTxDescriptor[NUM_RX_DESCRIPTORS];
uint32_t g_ui32RxDescIndex;
uint32_t g_ui32TxDescIndex;
//*****************************************************************************
//
// Transmit and receive buffers. These will typically be allocated within your
// network stack somewhere.
//
//*****************************************************************************
#define RX_BUFFER_SIZE 1536
uint8_t g_ppui8RxBuffer[NUM_RX_DESCRIPTORS][RX_BUFFER_SIZE];
/*******************************************************************************
 * Ethernet MAC loopback functions
 *******************************************************************************/
void ApplicationProcessFrame(uint32_t frameLen, void *dataBuffPtr){
int i =0;

for (i=0;i<frameLen;i++) {
    UARTprintf("The %d char is %d\n",i,(dataBuffPtr)); // check this -->what are getting here
    dataBuffPtr++;
}

}
//*****************************************************************************
//
// Initialize the transmit and receive DMA descriptors.
//
//*****************************************************************************
void
InitDescriptors(uint32_t ui32Base)
{
uint32_t ui32Loop;
//
// Initialize each of the transmit descriptors. Note that we leave the
// buffer pointer and size empty and the OWN bit clear here since we have
// not set up any transmissions yet.
//
for(ui32Loop = 0; ui32Loop < NUM_TX_DESCRIPTORS; ui32Loop++)
{
g_psTxDescriptor[ui32Loop].ui32Count = DES1_TX_CTRL_SADDR_INSERT;
g_psTxDescriptor[ui32Loop].DES3.pLink =
(ui32Loop == (NUM_TX_DESCRIPTORS - 1)) ?
g_psTxDescriptor : &g_psTxDescriptor[ui32Loop + 1];
g_psTxDescriptor[ui32Loop].ui32CtrlStatus =
(DES0_TX_CTRL_LAST_SEG | DES0_TX_CTRL_FIRST_SEG |
DES0_TX_CTRL_INTERRUPT | DES0_TX_CTRL_CHAINED |
DES0_TX_CTRL_IP_ALL_CKHSUMS);
}
//
// Initialize each of the receive descriptors. We clear the OWN bit here
// to make sure that the receiver doesn�t start writing anything
// immediately.
//
for(ui32Loop = 0; ui32Loop < NUM_RX_DESCRIPTORS; ui32Loop++)
{
g_psRxDescriptor[ui32Loop].ui32CtrlStatus = 0;
g_psRxDescriptor[ui32Loop].ui32Count =
(DES1_RX_CTRL_CHAINED |
(RX_BUFFER_SIZE << DES1_RX_CTRL_BUFF1_SIZE_S));
g_psRxDescriptor[ui32Loop].pvBuffer1 = g_ppui8RxBuffer[ui32Loop];
g_psRxDescriptor[ui32Loop].DES3.pLink =
(ui32Loop == (NUM_RX_DESCRIPTORS - 1)) ?
g_psRxDescriptor : &g_psRxDescriptor[ui32Loop + 1];
}
//
// Set the descriptor pointers in the hardware.
//
EMACRxDMADescriptorListSet(ui32Base, g_psRxDescriptor);
EMACTxDMADescriptorListSet(ui32Base, g_psTxDescriptor);
//
// Start from the beginning of both descriptor chains. We actually set
// the transmit descriptor index to the last descriptor in the chain
// since it will be incremented before use and this means the first
// transmission we perform will use the correct descriptor.
//
g_ui32RxDescIndex = 0;
g_ui32TxDescIndex = NUM_TX_DESCRIPTORS - 1;
}
//*****************************************************************************
//
// Read a packet from the DMA receive buffer and return the number of bytes
// read.
//
//*****************************************************************************
int32_t
ProcessReceivedPacket(void)
{
int_fast32_t i32FrameLen;
//
// By default, we assume we got a bad frame.
//
i32FrameLen = 0;
//
// Make sure that we own the receive descriptor.
//
if(!(g_psRxDescriptor[g_ui32RxDescIndex].ui32CtrlStatus & DES0_RX_CTRL_OWN))
{
//
// We own the receive descriptor so check to see if it contains a valid
// frame.
//
if(!(g_psRxDescriptor[g_ui32RxDescIndex].ui32CtrlStatus &
DES0_RX_STAT_ERR))
{
//
// We have a valid frame. First check that the "last descriptor"
// flag is set. We sized the receive buffer such that it can
// always hold a valid frame so this flag should never be clear at
// this point but...
//
if(g_psRxDescriptor[g_ui32RxDescIndex].ui32CtrlStatus &
DES0_RX_STAT_LAST_DESC)
{
//
// What size is the received frame?
//
    i32FrameLen =
    ((g_psRxDescriptor[g_ui32RxDescIndex].ui32CtrlStatus &
    DES0_RX_STAT_FRAME_LENGTH_M) >>
    DES0_RX_STAT_FRAME_LENGTH_S);
    //
    // Pass the received buffer up to the application to handle.
    //
    ApplicationProcessFrame(i32FrameLen,
    g_psRxDescriptor[g_ui32RxDescIndex].pvBuffer1);
    }
    }
    //
    // Now that we are finished dealing with this descriptor, hand
    // it back to the hardware. Note that we assume
    // ApplicationProcessFrame() is finished with the buffer at this point
    // so it is safe to reuse.
    //
    g_psRxDescriptor[g_ui32RxDescIndex].ui32CtrlStatus =
    DES0_RX_CTRL_OWN;
    //
    // Move on to the next descriptor in the chain.
    //
    g_ui32RxDescIndex++;
    if(g_ui32RxDescIndex == NUM_RX_DESCRIPTORS)
    {
    g_ui32RxDescIndex = 0;
    }
    }
    //
    // Return the Frame Length
    //
    return(i32FrameLen);
    }

//*****************************************************************************
//
// Transmit a packet from the supplied buffer. This function would be called
// directly by the application. pui8Buf points to the Ethernet frame to send
// and i32BufLen contains the number of bytes in the frame.
//
//*****************************************************************************
static int32_t
PacketTransmit(uint8_t *pui8Buf, int32_t i32BufLen)
{
//
// Wait for the transmit descriptor to free up.
//
while(g_psTxDescriptor[g_ui32TxDescIndex].ui32CtrlStatus &
DES0_TX_CTRL_OWN)
{
//
// Spin and waste time.
//
}
//
// Move to the next descriptor.
//
g_ui32TxDescIndex++;
if(g_ui32TxDescIndex == NUM_TX_DESCRIPTORS)
{
g_ui32TxDescIndex = 0;
}
//
// Fill in the packet size and pointer, and tell the transmitter to start
// work.
//
g_psTxDescriptor[g_ui32TxDescIndex].ui32Count = (uint32_t)i32BufLen;
g_psTxDescriptor[g_ui32TxDescIndex].pvBuffer1 = pui8Buf;
g_psTxDescriptor[g_ui32TxDescIndex].ui32CtrlStatus =
(DES0_TX_CTRL_LAST_SEG | DES0_TX_CTRL_FIRST_SEG |
DES0_TX_CTRL_INTERRUPT | DES0_TX_CTRL_IP_ALL_CKHSUMS |
DES0_TX_CTRL_CHAINED | DES0_TX_CTRL_OWN);
//
// Tell the DMA to reacquire the descriptor now that we�ve filled it in.
// This call is benign if the transmitter hasn�t stalled and checking
// the state takes longer than just issuing a poll demand so we do this
// for all packets.
//
EMACTxDMAPollDemand(EMAC0_BASE);
//
// Return the number of bytes sent.
//
return(i32BufLen);
}


//*****************************************************************************
//
// The interrupt handler for the Ethernet interrupt.
//
//*****************************************************************************
void
EthernetIntHandler(void)
{
uint32_t ui32Temp;
//
// Read and Clear the interrupt.
//
ui32Temp = EMACIntStatus(EMAC0_BASE, true);
EMACIntClear(EMAC0_BASE, ui32Temp);
//
// Check to see if an RX Interrupt has occurred.
//
if(ui32Temp & EMAC_INT_RECEIVE)
{
//
// Indicate that a packet has been received.
//
ProcessReceivedPacket();
}
}
/********************************************************************************/
/*Ethernet MAC loopback MAIN Driver
 * Set up Tx and Rx DMA
 * main.c
 */
int main(void) {

    uint32_t ui32User0, ui32User1,ui32Temp, ui32Loop,ui32PHYConfig, ui32SysClock;
    uint8_t ui8PHYAddr;
    uint8_t pui8MACAddr[6];
       // Run from the PLL at 120 MHz.
       //
       ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                              SYSCTL_OSC_MAIN |
                                              SYSCTL_USE_PLL |
                                              SYSCTL_CFG_VCO_480), 120000000);

       //
       // Configure the device pins.
       //
       PinoutSet(true, false);
       // Initialize the UART, clear the terminal, and print banner.
       // Set GPIO A0 and A1 as UART0 pins.
            //
            GPIOPinConfigure(GPIO_PA0_U0RX);
            GPIOPinConfigure(GPIO_PA1_U0TX);
            GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);



          UARTStdioConfig(0, 115200, ui32SysClock);
          UARTprintf("Hello\n");
          //******************************INITIALIZE PORT N GPIO ***********************************************************************************************//
          // Enable the GPIO port that is used for the on-board LED.
             //
             SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);


             //
             // Enable the GPIO pins for the LED (PN0).
             //
             GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0);

   //*****************************************************************************************************************************//
          // Read the MAC address from the user registers.
          //
          FlashUserGet(&ui32User0, &ui32User1);
          if((ui32User0 == 0xffffffff) || (ui32User1 == 0xffffffff))
              {
                  //
                  // We should never get here.  This is an error if the MAC address has
                  // not been programmed into the device.  Exit the program.
                  //
                  UARTprintf("MAC Address Not Programmed!");
                  while(1)
                  {
                  }
              }

          //
          // Convert the 24/24 split MAC address from NV ram into a 32/16 split MAC
          // address needed to program the hardware registers, then program the MAC
          // address into the Ethernet Controller registers.
          //
          pui8MACAddr[0] = ((ui32User0 >> 0) & 0xff);
          pui8MACAddr[1] = ((ui32User0 >> 8) & 0xff);
          pui8MACAddr[2] = ((ui32User0 >> 16) & 0xff);
          pui8MACAddr[3] = ((ui32User1 >> 0) & 0xff);
          pui8MACAddr[4] = ((ui32User1 >> 8) & 0xff);
          pui8MACAddr[5] = ((ui32User1 >> 16) & 0xff);

          //
          // Enable and reset the Ethernet modules.
          //
          SysCtlPeripheralEnable(SYSCTL_PERIPH_EMAC0);
      //    SysCtlPeripheralEnable(SYSCTL_PERIPH_EPHY0);
          SysCtlPeripheralReset(SYSCTL_PERIPH_EMAC0);
      //    SysCtlPeripheralReset(SYSCTL_PERIPH_EPHY0);
          //
          // Wait for the MAC to be ready.
          //
          while(!SysCtlPeripheralReady(SYSCTL_PERIPH_EMAC0))
          {
          }
          //
          // Set MAC configuration options.
          //

          //
              // Reset the MAC.
              //
              EMACReset(EMAC0_BASE);

             // Initialize the MAC and set the DMA mode.
              //
              EMACInit(EMAC0_BASE, ui32SysClock,EMAC_BCONFIG_MIXED_BURST | EMAC_BCONFIG_PRIORITY_FIXED, 4, 4,0);

              //
              // Set MAC configuration options.
              //
              EMACConfigSet(EMAC0_BASE,
              (EMAC_CONFIG_FULL_DUPLEX| EMAC_CONFIG_LOOPBACK |
              EMAC_CONFIG_CHECKSUM_OFFLOAD |
              EMAC_CONFIG_7BYTE_PREAMBLE |
              EMAC_CONFIG_IF_GAP_96BITS |
              EMAC_CONFIG_USE_MACADDR0 |
              EMAC_CONFIG_SA_FROM_DESCRIPTOR |
              EMAC_CONFIG_BO_LIMIT_1024),
              (EMAC_MODE_RX_STORE_FORWARD |
              EMAC_MODE_TX_STORE_FORWARD |
              EMAC_MODE_TX_THRESHOLD_64_BYTES |
              EMAC_MODE_RX_THRESHOLD_64_BYTES), 0);

              //
              // Initialize the Ethernet DMA descriptors.
              //
              InitDescriptors(EMAC0_BASE);
              //
              // Program the hardware with its MAC address (for filtering).
              //
              EMACAddrSet(EMAC0_BASE, 0, pui8MACAddr);

              //
              // Clear any pending interrupts.
              //
              EMACIntClear(EMAC0_BASE, EMACIntStatus(EMAC0_BASE, false));
              //
              // Mark the receive descriptors as available to the DMA to start
              // the receive processing.
              //
              for(ui32Loop = 0; ui32Loop < NUM_RX_DESCRIPTORS; ui32Loop++)
              {
              g_psRxDescriptor[ui32Loop].ui32CtrlStatus |= DES0_RX_CTRL_OWN;
              }
              //
              // Enable the Ethernet MAC transmitter and receiver.
              //
              EMACTxEnable(EMAC0_BASE);

              EMACRxEnable(EMAC0_BASE);
              //
              // Enable the Ethernet interrupt.
              //
              IntEnable(INT_EMAC0);
              //
              // Enable the Ethernet RX Packet interrupt source.
              //
              EMACIntEnable(EMAC0_BASE, EMAC_INT_RECEIVE);


while (1) {
    // do something here
    // Turn on the LED.
   GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, GPIO_PIN_0);

   SysCtlDelay(5000000);
                        // Turn off the LED.
                        //
    GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0);
        SysCtlDelay(10000000);
}// end while 1

              return 0;
}

Does anyone have sample code for this?

  • This is not a TI RTOS project
  • Hello Pavitra,
    I wanted to let you know we are working on your post. Unfortunately I am not experienced on using the Ethernet module. (Perhaps someone from the user community will jump in.)
  • Hello Pavitra,

    Attached is the code which allows the loopback. There were two things missing

    1. The PacketTransmit call was not there and hence nothing was being sent.

    2. The call EMACFrameFilterSet(EMAC0_BASE, (EMAC_FRMFILTER_RX_ALL)); was missing during the configuration which caused the MAC controller to disregard any packet not meant for the MAC Station Number

    After making the change, I can see the Ethernet Interrupt.

    #include <stdio.h>
    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_nvic.h"
    #include "inc/hw_types.h"
    #include "inc/hw_emac.h"
    #include "driverlib/flash.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/systick.h"
    #include "driverlib/timer.h"
    #include "driverlib/rom.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/emac.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    #include "utils/ustdlib.h"
    #include "drivers/pinout.h"
    
    //*****************************************************************************
    //
    // Defines for setting up the system clock.
    //
    //*****************************************************************************
    #define SYSTICKHZ               CLOCK_CONF_SECOND
    #define SYSTICKMS               (1000 / SYSTICKHZ)
    #define SYSTICKUS               (1000000 / SYSTICKHZ)
    #define SYSTICKNS               (1000000000 / SYSTICKHZ)
    
    //*****************************************************************************
    //
    // Ethernet DMA descriptors.
    //
    // The MAC hardware needs a minimum of 3 receive descriptors to operate. The
    // number used will be application-dependent and should be tuned for best
    // performance.
    //
    //*****************************************************************************
    #define NUM_TX_DESCRIPTORS 3
    #define NUM_RX_DESCRIPTORS 3
    tEMACDMADescriptor g_psRxDescriptor[NUM_TX_DESCRIPTORS];
    tEMACDMADescriptor g_psTxDescriptor[NUM_RX_DESCRIPTORS];
    uint32_t g_ui32RxDescIndex;
    uint32_t g_ui32TxDescIndex;
    
    //*****************************************************************************
    //
    // Transmit and receive buffers. These will typically be allocated within your
    // network stack somewhere.
    //
    //*****************************************************************************
    #define RX_BUFFER_SIZE 1536
    uint8_t g_ppui8RxBuffer[NUM_RX_DESCRIPTORS][RX_BUFFER_SIZE];
    
    /*******************************************************************************
     * Ethernet MAC loopback functions
     *******************************************************************************/
    void ApplicationProcessFrame(uint32_t frameLen, void *dataBuffPtr)
    {
        int i =0;
    
        for (i=0;i<frameLen;i++)
        {
            UARTprintf("The %d char is %d\n",i,(dataBuffPtr)); // check this -->what are getting here
            dataBuffPtr++;
        }
    }
    
    //*****************************************************************************
    //
    // Initialize the transmit and receive DMA descriptors.
    //
    //*****************************************************************************
    void
    InitDescriptors(uint32_t ui32Base)
    {
        uint32_t ui32Loop;
    
        //
        // Initialize each of the transmit descriptors. Note that we leave the
        // buffer pointer and size empty and the OWN bit clear here since we have
        // not set up any transmissions yet.
        //
    
        for(ui32Loop = 0; ui32Loop < NUM_TX_DESCRIPTORS; ui32Loop++)
        {
            g_psTxDescriptor[ui32Loop].ui32Count = DES1_TX_CTRL_SADDR_INSERT;
            g_psTxDescriptor[ui32Loop].DES3.pLink = (ui32Loop == (NUM_TX_DESCRIPTORS - 1)) ?
                    g_psTxDescriptor : &g_psTxDescriptor[ui32Loop + 1];
            g_psTxDescriptor[ui32Loop].ui32CtrlStatus = (DES0_TX_CTRL_LAST_SEG | DES0_TX_CTRL_FIRST_SEG |
                    DES0_TX_CTRL_INTERRUPT | DES0_TX_CTRL_CHAINED | DES0_TX_CTRL_IP_ALL_CKHSUMS);
        }
    
        //
        // Initialize each of the receive descriptors. We clear the OWN bit here
        // to make sure that the receiver doesn�t start writing anything
        // immediately.
        //
        for(ui32Loop = 0; ui32Loop < NUM_RX_DESCRIPTORS; ui32Loop++)
        {
            g_psRxDescriptor[ui32Loop].ui32CtrlStatus = 0;
            g_psRxDescriptor[ui32Loop].ui32Count = (DES1_RX_CTRL_CHAINED |
                    (RX_BUFFER_SIZE << DES1_RX_CTRL_BUFF1_SIZE_S));
            g_psRxDescriptor[ui32Loop].pvBuffer1 = g_ppui8RxBuffer[ui32Loop];
            g_psRxDescriptor[ui32Loop].DES3.pLink = (ui32Loop == (NUM_RX_DESCRIPTORS - 1)) ?
                    g_psRxDescriptor : &g_psRxDescriptor[ui32Loop + 1];
        }
    
        //
        // Set the descriptor pointers in the hardware.
        //
        EMACRxDMADescriptorListSet(ui32Base, g_psRxDescriptor);
        EMACTxDMADescriptorListSet(ui32Base, g_psTxDescriptor);
    
        //
        // Start from the beginning of both descriptor chains. We actually set
        // the transmit descriptor index to the last descriptor in the chain
        // since it will be incremented before use and this means the first
        // transmission we perform will use the correct descriptor.
        //
        g_ui32RxDescIndex = 0;
        g_ui32TxDescIndex = NUM_TX_DESCRIPTORS - 1;
    }
    
    //*****************************************************************************
    //
    // Read a packet from the DMA receive buffer and return the number of bytes
    // read.
    //
    //*****************************************************************************
    int32_t
    ProcessReceivedPacket(void)
    {
    
        int_fast32_t i32FrameLen;
    
        //
        // By default, we assume we got a bad frame.
        //
        i32FrameLen = 0;
    
        //
        // Make sure that we own the receive descriptor.
        //
        if(!(g_psRxDescriptor[g_ui32RxDescIndex].ui32CtrlStatus & DES0_RX_CTRL_OWN))
        {
            //
            // We own the receive descriptor so check to see if it contains a valid
            // frame.
            //
            if(!(g_psRxDescriptor[g_ui32RxDescIndex].ui32CtrlStatus &
                    DES0_RX_STAT_ERR))
            {
                //
                // We have a valid frame. First check that the "last descriptor"
                // flag is set. We sized the receive buffer such that it can
                // always hold a valid frame so this flag should never be clear at
                // this point but...
                //
                if(g_psRxDescriptor[g_ui32RxDescIndex].ui32CtrlStatus &
                        DES0_RX_STAT_LAST_DESC)
                {
                    //
                    // What size is the received frame?
                    //
                    i32FrameLen = ((g_psRxDescriptor[g_ui32RxDescIndex].ui32CtrlStatus &
                            DES0_RX_STAT_FRAME_LENGTH_M) >> DES0_RX_STAT_FRAME_LENGTH_S);
    
                    //
                    // Pass the received buffer up to the application to handle.
                    //
                    ApplicationProcessFrame(i32FrameLen, g_psRxDescriptor[g_ui32RxDescIndex].pvBuffer1);
                }
            }
    
            //
            // Now that we are finished dealing with this descriptor, hand
            // it back to the hardware. Note that we assume
            // ApplicationProcessFrame() is finished with the buffer at this point
            // so it is safe to reuse.
            //
            g_psRxDescriptor[g_ui32RxDescIndex].ui32CtrlStatus = DES0_RX_CTRL_OWN;
    
            //
            // Move on to the next descriptor in the chain.
            //
            g_ui32RxDescIndex++;
            if(g_ui32RxDescIndex == NUM_RX_DESCRIPTORS)
            {
                g_ui32RxDescIndex = 0;
            }
        }
    
        //
        // Return the Frame Length
        //
        return(i32FrameLen);
    }
    
    //*****************************************************************************
    //
    // Transmit a packet from the supplied buffer. This function would be called
    // directly by the application. pui8Buf points to the Ethernet frame to send
    // and i32BufLen contains the number of bytes in the frame.
    //
    //*****************************************************************************
    static int32_t
    PacketTransmit(uint8_t *pui8Buf, int32_t i32BufLen)
    {
        //
        // Wait for the transmit descriptor to free up.
        //
        while(g_psTxDescriptor[g_ui32TxDescIndex].ui32CtrlStatus & DES0_TX_CTRL_OWN)
        {
            //
            // Spin and waste time.
            //
        }
    
        //
        // Move to the next descriptor.
        //
        g_ui32TxDescIndex++;
        if(g_ui32TxDescIndex == NUM_TX_DESCRIPTORS)
        {
            g_ui32TxDescIndex = 0;
        }
    
        //
        // Fill in the packet size and pointer, and tell the transmitter to start
        // work.
        //
        g_psTxDescriptor[g_ui32TxDescIndex].ui32Count = (uint32_t)i32BufLen;
        g_psTxDescriptor[g_ui32TxDescIndex].pvBuffer1 = pui8Buf;
        g_psTxDescriptor[g_ui32TxDescIndex].ui32CtrlStatus =
                (DES0_TX_CTRL_LAST_SEG | DES0_TX_CTRL_FIRST_SEG |
                        DES0_TX_CTRL_INTERRUPT | DES0_TX_CTRL_IP_ALL_CKHSUMS |
                        DES0_TX_CTRL_CHAINED | DES0_TX_CTRL_OWN);
    
        //
        // Tell the DMA to reacquire the descriptor now that we�ve filled it in.
        // This call is benign if the transmitter hasn�t stalled and checking
        // the state takes longer than just issuing a poll demand so we do this
        // for all packets.
        //
        EMACTxDMAPollDemand(EMAC0_BASE);
    
        //
        // Return the number of bytes sent.
        //
        return(i32BufLen);
    }
    
    
    //*****************************************************************************
    //
    // The interrupt handler for the Ethernet interrupt.
    //
    //*****************************************************************************
    void
    EthernetIntHandler(void)
    {
        uint32_t ui32Temp;
    
        //
        // Read and Clear the interrupt.
        //
        ui32Temp = EMACIntStatus(EMAC0_BASE, true);
        EMACIntClear(EMAC0_BASE, ui32Temp);
    
        //
        // Check to see if an RX Interrupt has occurred.
        //
        if(ui32Temp & EMAC_INT_RECEIVE)
        {
            //
            // Indicate that a packet has been received.
            //
            ProcessReceivedPacket();
        }
    }
    /********************************************************************************/
    /*Ethernet MAC loopback MAIN Driver
     * Set up Tx and Rx DMA
     * main.c
     */
    int main(void)
    {
        uint32_t ui32User0, ui32User1,ui32Temp, ui32Loop,ui32PHYConfig, ui32SysClock;
        uint8_t ui8PHYAddr;
        uint8_t pui8MACAddr[6];
        uint8_t ui8Data[] = "This is a string";
    
        //
        // Run from the PLL at 120 MHz.
        //
        ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                               SYSCTL_OSC_MAIN |
                                               SYSCTL_USE_PLL |
                                               SYSCTL_CFG_VCO_480), 120000000);
    
        //
        // Configure the device pins.
        //
        PinoutSet(true, false);
        // Initialize the UART, clear the terminal, and print banner.
        // Set GPIO A0 and A1 as UART0 pins.
        //
        GPIOPinConfigure(GPIO_PA0_U0RX);
        GPIOPinConfigure(GPIO_PA1_U0TX);
        GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        UARTStdioConfig(0, 115200, ui32SysClock);
        UARTprintf("Hello\n");
        //******************************INITIALIZE PORT N GPIO ***********************************************************************************************//
        // Enable the GPIO port that is used for the on-board LED.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
    
        //
        // Enable the GPIO pins for the LED (PN0).
        //
        GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0);
    
        //*****************************************************************************************************************************//
        // Read the MAC address from the user registers.
        //
        FlashUserGet(&ui32User0, &ui32User1);
        if((ui32User0 == 0xffffffff) || (ui32User1 == 0xffffffff))
        {
            //
            // We should never get here.  This is an error if the MAC address has
            // not been programmed into the device.  Exit the program.
            //
            UARTprintf("MAC Address Not Programmed!");
            while(1)
            {
            }
        }
    
        //
        // Convert the 24/24 split MAC address from NV ram into a 32/16 split MAC
        // address needed to program the hardware registers, then program the MAC
        // address into the Ethernet Controller registers.
        //
        pui8MACAddr[0] = ((ui32User0 >> 0) & 0xff);
        pui8MACAddr[1] = ((ui32User0 >> 8) & 0xff);
        pui8MACAddr[2] = ((ui32User0 >> 16) & 0xff);
        pui8MACAddr[3] = ((ui32User1 >> 0) & 0xff);
        pui8MACAddr[4] = ((ui32User1 >> 8) & 0xff);
        pui8MACAddr[5] = ((ui32User1 >> 16) & 0xff);
    
        //
        // Enable and reset the Ethernet modules.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_EMAC0);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_EPHY0);
        SysCtlPeripheralReset(SYSCTL_PERIPH_EMAC0);
        SysCtlPeripheralReset(SYSCTL_PERIPH_EPHY0);
    
        //
        // Wait for the MAC to be ready.
        //
        while(!SysCtlPeripheralReady(SYSCTL_PERIPH_EMAC0))
        {
        }
    
        //
        // Reset the MAC.
        //
        EMACReset(EMAC0_BASE);
    
        //
        // Set MAC configuration options.
        // Initialize the MAC and set the DMA mode.
        //
        EMACInit(EMAC0_BASE, ui32SysClock,EMAC_BCONFIG_MIXED_BURST | EMAC_BCONFIG_PRIORITY_FIXED, 4, 4,0);
    
        //
        // Set MAC configuration options.
        //
        EMACConfigSet(EMAC0_BASE,
                  (EMAC_CONFIG_FULL_DUPLEX| EMAC_CONFIG_LOOPBACK |
                  EMAC_CONFIG_CHECKSUM_OFFLOAD |
                  EMAC_CONFIG_7BYTE_PREAMBLE |
                  EMAC_CONFIG_IF_GAP_96BITS |
                  EMAC_CONFIG_USE_MACADDR0 |
                  EMAC_CONFIG_SA_FROM_DESCRIPTOR |
                  EMAC_CONFIG_BO_LIMIT_1024),
                  (EMAC_MODE_RX_STORE_FORWARD |
                  EMAC_MODE_TX_STORE_FORWARD |
                  EMAC_MODE_TX_THRESHOLD_64_BYTES |
                  EMAC_MODE_RX_THRESHOLD_64_BYTES), 0);
    
        //
        // Initialize the Ethernet DMA descriptors.
        //
        InitDescriptors(EMAC0_BASE);
    
        //
        // Program the hardware with its MAC address (for filtering).
        //
        EMACAddrSet(EMAC0_BASE, 0, pui8MACAddr);
        EMACFrameFilterSet(EMAC0_BASE, (EMAC_FRMFILTER_RX_ALL));
    
        //
        // Clear any pending interrupts.
        //
        EMACIntClear(EMAC0_BASE, EMACIntStatus(EMAC0_BASE, false));
    
        //
        // Mark the receive descriptors as available to the DMA to start
        // the receive processing.
        //
        for(ui32Loop = 0; ui32Loop < NUM_RX_DESCRIPTORS; ui32Loop++)
        {
            g_psRxDescriptor[ui32Loop].ui32CtrlStatus |= DES0_RX_CTRL_OWN;
        }
    
        //
        // Enable the Ethernet MAC transmitter and receiver.
        //
        EMACTxEnable(EMAC0_BASE);
        EMACRxEnable(EMAC0_BASE);
    
        //
        // Enable the Ethernet interrupt.
        //
        IntEnable(INT_EMAC0);
    
        //
        // Enable the Ethernet RX Packet interrupt source.
        //
        EMACIntEnable(EMAC0_BASE, EMAC_INT_RECEIVE);
    
        while (1)
        {
            // do something here
            // Turn on the LED.
            PacketTransmit(&ui8Data[0], 10);
            GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, GPIO_PIN_0);
    
            SysCtlDelay(5000000);
    
            // Turn off the LED.
            GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0);
            SysCtlDelay(10000000);
        }
    
    }