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.

TM4C1294NCPDT: Ethernet Bootloader ,boot_demo_emac_rom

Part Number: TM4C1294NCPDT

Tool/software:

Hi Team,

I trying to do firmware upgrade using ethernet bootloader code (boot_demo_emac_rom)(TM4C1294NCPDT),

The firmware upgrade is working fine using LM Flash in Ethernet,

But my requirement is to encrypt the HEX file using 128 bit ECB AES encryption,

The problem is I could not extract the payload that is Hex File DATA in the boot_demo_emac_rom code (swupdate.c file)

Can you please help me to get the payload data from which function, variable in this boot_demo_emac_rom and explain how this project will work 

can You please help me to highlight which function, variable from where I need extract the TFTP Hex file data

I also attached my custom swupdate.c and boot_demo_emac_rom.c  file for your reference

//*****************************************************************************
//
// swupdate.c - A module wrapping the Ethernet bootloader software update
//              functionality.
//
// Copyright (c) 2008-2020 Texas Instruments Incorporated.  All rights reserved.
// Software License Agreement
// 
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
// 
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
// 
// This is part of revision 2.2.0.295 of the Tiva Utility Library.
//
//*****************************************************************************

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_aes.h"
#include "inc/hw_memmap.h"
#include "inc/hw_nvic.h"
#include "inc/hw_ints.h"
#include "inc/hw_sysctl.h"
#include "driverlib/debug.h"
#include "driverlib/gpio.h"
#include "driverlib/fpu.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "inc/hw_types.h"
#include "driverlib/flash.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/systick.h"
#include "utils/lwiplib.h"
#include "utils/swupdate.h"
#include "driverlib/pin_map.h"
#include "driverlib/aes.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "driverlib/udma.h"
#include "driverlib/rom_map.h"
#include "utils/uartstdio.h"



int Binarydecryption(int8_t *pi8Datapayload, int8_t *pui8PlainText);
//*****************************************************************************
//
// Configuration defines.
//
//*****************************************************************************
#define CCM_LOOP_TIMEOUT        500000
//*****************************************************************************
//
// Sample plaintext, ciphertext, and key from the NIST SP 800-38A document.
//
//*****************************************************************************


uint32_t *g_pui32AES128Key = "aesEncryptionKey";


//*****************************************************************************
//
//! \addtogroup swupdate_api
//! @{
//
//*****************************************************************************

//*****************************************************************************
//
// The UDP port used to send the remote firmware update request signal.  This
// is the well-known port associated with "discard" function and is also used
// by some Wake-On-LAN implementations.
//
//*****************************************************************************
#define MPACKET_PORT            9

//*****************************************************************************
//
// The length of the various parts of the remote firmware update request magic
// packet and its total length.  This contains a 6 byte header followed by 4
// copies of the target MAC address.
//
//*****************************************************************************
#define MPACKET_HEADER_LEN      6
#define MPACKET_MAC_REP         4
#define MPACKET_MAC_LEN         6
#define MPACKET_LEN             (MPACKET_HEADER_LEN +                         \
                                 (MPACKET_MAC_REP * MPACKET_MAC_LEN))

//*****************************************************************************
//
// The marker byte used at the start of the magic packet.  This is repeated
// MPACKET_HEADER_LEN times.
//
//*****************************************************************************
#define MPACKET_MARKER          0xAA

//*****************************************************************************
//
// The callback function which is used to determine whether or not the
// application wants to allow a remotely-requested firmware update.
//
//*****************************************************************************
tSoftwareUpdateRequested g_pfnUpdateCallback = NULL;

//*****************************************************************************
//
// A pointer to the remote firmware update signal PCB data structure.
//
//*****************************************************************************
static struct udp_pcb *g_psMagicPacketPCB = NULL;

//*****************************************************************************
//
// The MAC address for this board.
//
//*****************************************************************************
static uint8_t g_pui8MACAddr[6];

//*****************************************************************************
//
// Round up length to nearest 16 byte boundary.  This is needed because all
// four data registers must be written at once.  This is handled in the AES
// driver, but if using uDMA, the length must rounded up.
//
//*****************************************************************************
uint32_t
LengthRoundUp(uint32_t ui32Length)
{
    uint32_t ui32Remainder;

    ui32Remainder = ui32Length % 16;
    if(ui32Remainder == 0)
    {
        return(ui32Length);
    }
    else
    {
        return(ui32Length + (16 - ui32Remainder));
    }
}

//*****************************************************************************
//
// The AES interrupt handler and interrupt flags.
//
//*****************************************************************************
static volatile bool g_bContextInIntFlag;
static volatile bool g_bDataInIntFlag;
static volatile bool g_bContextOutIntFlag;
static volatile bool g_bDataOutIntFlag;


//*****************************************************************************
//
// Configure the UART and its pins.  This must be called before UARTprintf().
//
//*****************************************************************************
void
ConfigureUART(void)
{
    //
    // Enable the GPIO Peripheral used by the UART.
    //
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    //
    // Enable UART0
    //
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

    //
    // Configure GPIO Pins for UART mode.
    //
    MAP_GPIOPinConfigure(GPIO_PA0_U0RX);
    MAP_GPIOPinConfigure(GPIO_PA1_U0TX);
    MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    //
    // Use the internal 16MHz oscillator as the UART clock source.
    //
    MAP_UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);

    //
    // Initialize the UART for console I/O.
    //
    UARTStdioConfig(0, 115200, 16000000);
}


void
AESIntHandler(void)
{
    uint32_t ui32IntStatus;

    //
    // Read the AES masked interrupt status.
    //
    ui32IntStatus = MAP_AESIntStatus(AES_BASE, true);

    //
    // Print a different message depending on the interrupt source.
    //
    if(ui32IntStatus & AES_INT_CONTEXT_IN)
    {
        MAP_AESIntDisable(AES_BASE, AES_INT_CONTEXT_IN);
        g_bContextInIntFlag = true;
        UARTprintf(" Context input registers are ready.\n");
    }
    if(ui32IntStatus & AES_INT_DATA_IN)
    {
        MAP_AESIntDisable(AES_BASE, AES_INT_DATA_IN);
        g_bDataInIntFlag = true;
        UARTprintf(" Data FIFO is ready to receive data.\n");
    }
    if(ui32IntStatus & AES_INT_CONTEXT_OUT)
    {
        MAP_AESIntDisable(AES_BASE, AES_INT_CONTEXT_OUT);
        g_bContextOutIntFlag = true;
        UARTprintf(" Context output registers are ready.\n");
    }
    if(ui32IntStatus & AES_INT_DATA_OUT)
    {
        MAP_AESIntDisable(AES_BASE, AES_INT_DATA_OUT);
        g_bDataOutIntFlag = true;
        UARTprintf(" Data FIFO is ready to provide data.\n");
    }

}


//*****************************************************************************
//
// Perform an decryption operation.
//
//*****************************************************************************
bool
AESECBDecrypt(uint32_t ui32Keysize, uint32_t *pui32Src, uint32_t *pui32Dst,
              uint32_t *pui32Key, uint32_t ui32Length, bool bUseDMA)
{
    //
    // Perform a soft reset.
    //
    MAP_AESReset(AES_BASE);

    //
    // Clear the interrupt flags.
    //
    g_bContextInIntFlag = false;
    g_bDataInIntFlag = false;
    g_bContextOutIntFlag = false;
    g_bDataOutIntFlag = false;


    //
    // Enable all interrupts.
    //
    MAP_AESIntEnable(AES_BASE, (AES_INT_CONTEXT_IN | AES_INT_CONTEXT_OUT |
                                AES_INT_DATA_IN | AES_INT_DATA_OUT));

    //
    // Configure the AES module.
    //
    MAP_AESConfigSet(AES_BASE, (ui32Keysize | AES_CFG_DIR_DECRYPT |
                                AES_CFG_MODE_ECB));

    //
    // Write the key.
    //
    MAP_AESKey1Set(AES_BASE, pui32Key, ui32Keysize);

    //
    // Depending on the argument, perform the decryption
    // with or without uDMA.
    //


        //
        // Perform the decryption.
        //
        MAP_AESDataProcess(AES_BASE, pui32Src, pui32Dst, ui32Length);


    return(true);
}

//*****************************************************************************
//
// Receives a UDP port 9 packet from lwIP.
//
// \param arg is not used in this implementation.
// \param pcb is the pointer to the UDB control structure.
// \param p is the pointer to the PBUF structure containing the packet data.
// \param addr is the source (remote) IP address for this packet.
// \param port is the source (remote) port for this packet.
//
// This function is called when the lwIP TCP/IP stack has an incoming
// UDP packet to be processed on the remote firmware update signal port.
//
// \return None.
//
//*****************************************************************************
static void
SoftwareUpdateUDPReceive(void *arg, struct udp_pcb *pcb, struct pbuf *p,
                         struct ip_addr *addr, u16_t port)
{
    int8_t *encryptedpi8Data = NULL;//p->payload;
    int8_t *pi8Data = p->payload;
    int8_t *pi8payload = p->payload;
    uint32_t ui32Loop, ui32MACLoop;
    uint32_t ui32NewIPAddress;
    int i=0;

    //Binarydecryption(encryptedpi8Data,pi8Data);


     ui32NewIPAddress = lwIPLocalIPAddrGet();
     UARTprintf("IP Address: ");
     DisplayIPAddress(ui32NewIPAddress);
     UARTprintf("\n");

     for(i=0;i< 512;i++)
     {
         UARTprintf("%x\t",*pi8Data & 0x000000FF);
         pi8Data++;
         if((i % 16) == 0)
         {
             UARTprintf("\n");
         }
     }

    //
    // Check that the packet length is what we expect.  If not, ignore the
    // packet.
    //
    if(p->len == MPACKET_LEN)
    {
        //
        // The length matches so now look for the 6 byte header
        //
        for(ui32Loop = 0; ui32Loop < MPACKET_HEADER_LEN; ui32Loop++)
        {

            //
            // Does this header byte match the expected marker?
            //
            if((*pi8Data & 0x000000FF)!= MPACKET_MARKER)
            {
                //
                // No - free the buffer and return - this is not a packet
                // we are interested in.
                //
                pbuf_free(p);
                return;
            }
            else
            {
                //
                // Byte matched so move on to the next one.
                //
                pi8Data++;

            }
        }



    }
    else
    {
        //
        // No - free the buffer and return - this is not a packet
        // we are interested in.
        //
        pbuf_free(p);
        return;
    }

    //
    // If we get here, the packet length and header markers indicate
    // that this is a remote firmware update request.  Now check that it
    // is for us and that it contains the required number of copies of
    // the MAC address.
    //
    UARTprintf("\n");
    //
    // Loop through each of the expected MAC address copies.
    //
    for(ui32Loop = 0; ui32Loop < MPACKET_MAC_REP; ui32Loop++)
    {
        //
        // Loop through each byte of the MAC address in this
        // copy.
        //
        for(ui32MACLoop = 0; ui32MACLoop < MPACKET_MAC_LEN; ui32MACLoop++)
        {

            //
            // Does the payload MAC address byte match what we expect?
            //
            if((*pi8Data & 0x000000FF) != g_pui8MACAddr[ui32MACLoop])
            {
                //
                // No match - free the packet and return.
                //
                pbuf_free(p);
                return;
            }
            else
            {
                //
                // Byte matched so move on to the next one.
                //
                pi8Data++;

            }
        }
    }


    //
    // Free the pbuf since we are finished with it now.
    //
    pbuf_free(p);

    //
    // If we get this far, we've received a valid remote firmare update
    // request targetted at this board.  Signal this to the application
    // if we have a valid callback pointer.
    //
    if(g_pfnUpdateCallback)
    {
        g_pfnUpdateCallback();
    }
}


//*****************************************************************************
//
// Initialize the AES and CCM modules.
//
//*****************************************************************************
bool
AESInit(void)
{
    uint32_t ui32Loop;

    //
    // Check that the CCM peripheral is present.
    //
    if(!MAP_SysCtlPeripheralPresent(SYSCTL_PERIPH_CCM0))
    {
        UARTprintf("No CCM peripheral found!\n");

        //
        // Return failure.
        //
        return(false);
    }

    //
    // The hardware is available, enable it.
    //
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_CCM0);

    //
    // Wait for the peripheral to be ready.
    //
    ui32Loop = 0;
    while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_CCM0))
    {
        //
        // Increment our poll counter.
        //
        ui32Loop++;

        if(ui32Loop > CCM_LOOP_TIMEOUT)
        {
            //
            // Timed out, notify and spin.
            //
            UARTprintf("Time out on CCM ready after enable.\n");

            //
            // Return failure.
            //
            return(false);
        }
    }

    //
    // Reset the peripheral to ensure we are starting from a known condition.
    //
    MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_CCM0);

    //
    // Wait for the peripheral to be ready again.
    //
    ui32Loop = 0;
    while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_CCM0))
    {
        //
        // Increment our poll counter.
        //
        ui32Loop++;

        if(ui32Loop > CCM_LOOP_TIMEOUT)
        {
            //
            // Timed out, spin.
            //
            UARTprintf("Time out on CCM ready after reset.\n");

            //
            // Return failure.
            //
            return(false);
        }
    }

    //
    // Return initialization success.
    //
    return(true);
}


int Binarydecryption(int8_t *pi8Datapayload, int8_t *pui8PlainText)
{
            int8_t ui32Errors;
            uint32_t ui32Keysize;

            uint8_t  ui8Loop;


        //
        // Initialize local variables.
        //
        ui32Errors = 0;

        //
        // Enable stacking for interrupt handlers.  This allows floating-point
        // instructions to be used within interrupt handlers, but at the expense of
        // extra stack usage.
        //
        MAP_FPUStackingEnable();

        //
        // Configure the system clock to run off the internal 16MHz oscillator.
        //
       // MAP_SysCtlClockFreqSet(SYSCTL_OSC_INT | SYSCTL_USE_OSC, 16000000);

        //
        // Enable AES interrupts.
        //
        MAP_IntEnable(INT_AES0);

        //
        // Enable debug output on UART0 and print a welcome message.
        //

        UARTprintf("Starting AES ECB decryption demo.\n");




        //
        // Initialize the CCM and AES modules.
        //
        if(!AESInit())
        {
            UARTprintf("Initialization of the AES module failed.\n");
            ui32Errors |= 0x00000001;
        }

        //
        // Perform the same operation with 128bit key first, then 256bit key.
        //

            ui8Loop = 0;
            ui32Keysize = (ui8Loop == 0)?AES_CFG_KEY_SIZE_128BIT:
                                         AES_CFG_KEY_SIZE_256BIT;
            UARTprintf("\nKey Size: %sbit\n", ((ui8Loop == 0)?"128":"256"));

            //
            // Clear the array containing the plaintext.
            //
            /*for(ui32Idx = 0; ui32Idx < 16; ui32Idx++)
            {
                pui32PlainText[ui32Idx] = 0;
            }*/

            //
            // Perform the decryption without uDMA.
            //
            UARTprintf("Performing decryption without uDMA.\n");
           /* AESECBDecrypt(ui32Keysize,
                   pi8Datapayload,
                   pui8PlainText,
                   g_pui32AES128Key,
                   64, false);*/

            //
            // Check the result.
            //
            /*for(ui32Idx = 0; ui32Idx < 16; ui32Idx++)
            {
                if(pui32PlainText[ui32Idx] != g_pui32AESPlainText[ui32Idx])
                {
                    UARTprintf("Plaintext mismatch on word %d. Exp: 0x%x, Act: 0x%x\n",
                               ui32Idx, g_pui32AESPlainText[ui32Idx],
                               pui32PlainText[ui32Idx]);
                    ui32Errors |= (ui32Idx << 16) | 0x00000002;
                }
            }*/

            //
            // Clear the array containing the plaintext.
            //
            /*for(ui32Idx = 0; ui32Idx < 16; ui32Idx++)
            {
                pui32PlainText[ui32Idx] = 0;
            }*/



            //
            // Finished.
            //
            if(ui32Errors)
            {
                UARTprintf("Demo failed with error code 0x%x.\n", ui32Errors);

            }
            else
            {
                UARTprintf("Demo completed successfully.\n");

            }



}
//*****************************************************************************
//
//! Initializes the remote Ethernet software update notification feature.
//!
//! \param pfnCallback is a pointer to a function which will be called whenever
//! a remote firmware update request is received.  If the application wishes
//! to allow the update to go ahead, it must call SoftwareUpdateBegin() from
//! non-interrupt context after the callback is received.  Note that the
//! callback will most likely be made in interrupt context so it is not safe
//! to call SoftwareUpdateBegin() from within the callback itself.
//!
//! This function may be used on Ethernet-enabled parts to support
//! remotely-signaled firmware updates over Ethernet.  The LM Flash Programmer
//! (LMFlash.exe) application sends a magic packet to UDP port 9 whenever the
//! user requests an Ethernet-based firmware update.  This packet consists of
//! 6 bytes of 0xAA followed by the target MAC address repeated 4 times.
//! This function starts listening on UDP port 9 and, if a magic packet
//! matching the MAC address of this board is received, makes a call to the
//! provided callback function to indicate that an update has been requested.
//!
//! The callback function provided here will typically be called in the context
//! of the lwIP Ethernet interrupt handler.  It is not safe to call
//! SoftwareUpdateBegin() in this context so the application should use the
//! callback to signal code running in a non-interrupt context to perform the
//! update if it is to be allowed.
//!
//! UDP port 9 is chosen for this function since this is the well-known port
//! associated with ``discard'' operation.  In other words, any other system
//! receiving the magic packet will simply ignore it.  The actual magic packet
//! used is modeled on Wake-On-LAN which uses a similar structure (6 bytes of
//! 0xFF followed by 16 repetitions of the target MAC address).  Some
//! Wake-On-LAN implementations also use UDP port 9 for their signaling.
//!
//! \note Applications using this function must initialize the lwIP stack prior
//! to making this call and must ensure that the lwIPTimer() function is called
//! periodically.  lwIP UDP must be enabled in lwipopts.h to ensure that the
//! magic packets can be received.
//!
//! \return None.
//
//*****************************************************************************
void
SoftwareUpdateInit(tSoftwareUpdateRequested pfnCallback)
{
    uint32_t ui32User0, ui32User1;

    //
    // Remember the callback function pointer we have been given.
    //
    g_pfnUpdateCallback = pfnCallback;

    //
    // Get the MAC address from the user registers in NV ram.
    //
    FlashUserGet(&ui32User0, &ui32User1);

    //
    // Convert the 24/24 split MAC address from NV ram into a MAC address
    // array.
    //
    g_pui8MACAddr[0] = ui32User0 & 0xff;
    g_pui8MACAddr[1] = (ui32User0 >> 8) & 0xff;
    g_pui8MACAddr[2] = (ui32User0 >> 16) & 0xff;
    g_pui8MACAddr[3] = ui32User1 & 0xff;
    g_pui8MACAddr[4] = (ui32User1 >> 8) & 0xff;
    g_pui8MACAddr[5] = (ui32User1 >> 16) & 0xff;



    //
    // Set up a UDP PCB to allow us to receive the magic packets sent from
    // LMFlash.  These may be sent to port 9 from any port on the source
    // machine so we do not call udp_connect here (since this causes lwIP to
    // filter any packet that did not originate from port 9 too).
    //
    g_psMagicPacketPCB = udp_new();
    udp_recv(g_psMagicPacketPCB, SoftwareUpdateUDPReceive, NULL);
    udp_bind(g_psMagicPacketPCB, IP_ADDR_ANY, MPACKET_PORT);
}

//*****************************************************************************
//
//! Passes control to the bootloader and initiates a remote software update
//! over Ethernet.
//!
//! This function passes control to the bootloader and initiates an update of
//! the main application firmware image via BOOTP across Ethernet.  This
//! function may only be used on parts supporting Ethernet and in cases where
//! the Ethernet boot loader is in use alongside the main application image.
//! It must not be called in interrupt context.
//!
//! Applications wishing to make use of this function must be built to
//! operate with the bootloader.  If this function is called on a system
//! which does not include the bootloader, the results are unpredictable.
//!
//! \note It is not safe to call this function from within the callback
//! provided on the initial call to SoftwareUpdateInit().  The application
//! must use the callback to signal a pending update (assuming the update is to
//! be permitted) to some other code running in a non-interrupt context.
//!
//! \return Never returns.
//
//*****************************************************************************
void
SoftwareUpdateBegin(uint32_t ui32SysClock)
{
    //
    // Disable all processor interrupts.  Instead of disabling them
    // one at a time (and possibly missing an interrupt if new sources
    // are added), a direct write to NVIC is done to disable all
    // peripheral interrupts.
    //
    HWREG(NVIC_DIS0) = 0xffffffff;
    HWREG(NVIC_DIS1) = 0xffffffff;
    HWREG(NVIC_DIS2) = 0xffffffff;
    HWREG(NVIC_DIS3) = 0xffffffff;
    HWREG(NVIC_DIS4) = 0xffffffff;

    //
    // Also disable the SysTick interrupt.
    //
    SysTickIntDisable();
    SysTickDisable();

    //
    // Return control to the boot loader.  This is a call to the SVC
    // handler in the flashed-based boot loader, or to the ROM if configured.
    //
#if ((defined ROM_UpdateEMAC) && !(defined USE_FLASH_BOOT_LOADER))
    ROM_UpdateEMAC(ui32SysClock);
#else
    (*((void (*)(void))(*(uint32_t *)0x2c)))();
#endif
}

//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************

//*****************************************************************************
//
// boot_demo_emac_rom.c - Example demonstrating the use of the ROM Ethernet
//                        boot loader.
//
// Copyright (c) 2008-2020 Texas Instruments Incorporated.  All rights reserved.
// Software License Agreement
// 
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
// 
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
// 
// This is part of revision 2.2.0.295 of the EK-TM4C1294XL Firmware Package.
//
//*****************************************************************************

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_gpio.h"
#include "inc/hw_memmap.h"
#include "inc/hw_nvic.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/flash.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "utils/lwiplib.h"
#include "utils/swupdate.h"
#include "utils/ustdlib.h"
#include "utils/uartstdio.h"
#include "drivers/pinout.h"
//*****************************************************************************
//
//! \addtogroup example_list
//! <h1>ROM Boot Loader Ethernet Demo (boot_demo_emac_rom)</h1>
//!
//! An example to demonstrate the use of remote update signaling with the
//! ROM-based Ethernet boot loader.  This application configures the Ethernet
//! controller and acquires an IP address.  It then listens for a
//! ``magic packet'' telling it that a firmware upgrade request is being made
//! and, when this packet is received, transfers control to the ROM boot loader
//! to perform the upgrade.
//
//*****************************************************************************

//*****************************************************************************
//
// The number of SysTick ticks per second.
//
//*****************************************************************************
#define TICKS_PER_SECOND 100

//****************************************************************************
//
// The variable g_ui32SysClock contains the system clock frequency in Hz.
//
//****************************************************************************
uint32_t g_ui32SysClock;

//*****************************************************************************
//
// A global flag used to indicate if a remote firmware update request has been
// received.
//
//*****************************************************************************
static volatile bool g_bFirmwareUpdate = false;

//*****************************************************************************
//
// Buffers used to hold the Ethernet MAC and IP addresses for the board.
//
//*****************************************************************************
#define SIZE_MAC_ADDR_BUFFER 32
#define SIZE_IP_ADDR_BUFFER 32
char g_pcMACAddr[SIZE_MAC_ADDR_BUFFER];
char g_pcIPAddr[SIZE_IP_ADDR_BUFFER];

//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line) 
{
}
#endif

//*****************************************************************************
//
// This is the handler for this SysTick interrupt.  We use this to provide the
// required timer call to the lwIP stack.
//
//*****************************************************************************
void
SysTickIntHandler(void)
{
    //
    // Call the lwIP timer.
    //
    //
    lwIPTimer(1000 / TICKS_PER_SECOND);
}

//*****************************************************************************
//
// This function is called by the software update module whenever a remote
// host requests to update the firmware on this board.  We set a flag that
// will cause the main loop to exit and transfer control to the boot loader.
//
// IMPORTANT:
// Note that this callback is made in interrupt context and, since it is not
// permitted to transfer control to the boot loader from within an interrupt,
// we can't just call SoftwareUpdateBegin() here.
//
//*****************************************************************************
void
SoftwareUpdateRequestCallback(void)
{
    g_bFirmwareUpdate = true;
}



void
DisplayIPAddress(uint32_t ui32Addr)
{
    char pcBuf[16];

    //
    // Convert the IP Address into a string.
    //
    usprintf(pcBuf, "%d.%d.%d.%d", ui32Addr & 0xff, (ui32Addr >> 8) & 0xff,
            (ui32Addr >> 16) & 0xff, (ui32Addr >> 24) & 0xff);

    //
    // Display the string.
    //
    UARTprintf(pcBuf);
}
//*****************************************************************************
//
// Perform the initialization steps required to start up the Ethernet controller
// and lwIP stack.
//
//*****************************************************************************
void
SetupForEthernet(void)
{
    uint32_t ui32User0, ui32User1;
    uint8_t pui8MACAddr[6];





    //
    // Configure SysTick for a 100Hz interrupt.
    //
    MAP_SysTickPeriodSet(g_ui32SysClock / TICKS_PER_SECOND);
    MAP_SysTickEnable();
    MAP_SysTickIntEnable();

    //
    // Get the MAC address from the UART0 and UART1 registers in NV ram.
    //
    MAP_FlashUserGet(&ui32User0, &ui32User1);

    //
    // Convert the 24/24 split MAC address from NV ram into a MAC address
    // array.
    //
    pui8MACAddr[0] = ui32User0 & 0xff;
    pui8MACAddr[1] = (ui32User0 >> 8) & 0xff;
    pui8MACAddr[2] = (ui32User0 >> 16) & 0xff;
    pui8MACAddr[3] = ui32User1 & 0xff;
    pui8MACAddr[4] = (ui32User1 >> 8) & 0xff;
    pui8MACAddr[5] = (ui32User1 >> 16) & 0xff;

    //
    // Format this address into the string used by the relevant widget.
    //


    usnprintf(g_pcMACAddr, SIZE_MAC_ADDR_BUFFER,
              "MAC: %02X-%02X-%02X-%02X-%02X-%02X",
              pui8MACAddr[0], pui8MACAddr[1], pui8MACAddr[2], pui8MACAddr[3],
              pui8MACAddr[4], pui8MACAddr[5]);

    //
    // Remember that we don't have an IP address yet.
    //
    usnprintf(g_pcIPAddr, SIZE_IP_ADDR_BUFFER, "IP: Not assigned");

    //
    // Initialize the lwIP TCP/IP stack.
    //
    lwIPInit(g_ui32SysClock, pui8MACAddr, 0, 0xFFFFFF00, 0, IPADDR_USE_DHCP);




    //
    // Start the remote software update module.
    //
    SoftwareUpdateInit(SoftwareUpdateRequestCallback);


}

//*****************************************************************************
//
// A simple application demonstrating use of the boot loader.
//
//*****************************************************************************
int
main(void)
{
    //
    // Enable lazy stacking for interrupt handlers.  This allows floating-point
    // instructions to be used within interrupt handlers, but at the expense of
    // extra stack usage.
    //
    MAP_FPULazyStackingEnable();

    //
    // Run from the PLL at 120 MHz.
    // Note: SYSCTL_CFG_VCO_240 is a new setting provided in TivaWare 2.2.x and
    // later to better reflect the actual VCO speed due to SYSCTL#22.
    //
    g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                             SYSCTL_OSC_MAIN |
                                             SYSCTL_USE_PLL |
                                             SYSCTL_CFG_VCO_240), 120000000);



        //
        // Configure the device pins.
        //
        PinoutSet(true, false);

       //
       // Configure debug port for internal use.
       //
       UARTStdioConfig(0, 115200, g_ui32SysClock);

       //
       // Clear the terminal and print a banner.
       //
       UARTprintf("\033[2J\033[H");
       UARTprintf("Ethernet Boot-loader\n\n");
    //
    // Initialize the peripherals for the Ethernet boot loader.
    //
    SetupForEthernet();

    //
    // Configure Port N pin 1 as output.
    //
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
    while(!(MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPION)));
    MAP_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_1);

    //
    // If the Switch SW1 is not pressed then blink the LED D1 at 1 Hz rate.
    // On switch SW1 press detection exit the blinking program and jump to
    // the flash boot loader.
    //
    while(!g_bFirmwareUpdate)
    {
        MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, 0x0);
        MAP_SysCtlDelay(g_ui32SysClock / 6);
        MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, GPIO_PIN_1);
        MAP_SysCtlDelay(g_ui32SysClock / 6);
    }

    //
    // Before passing control make sure that the LED is turned OFF.
    //
    MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, 0x0);
    
    //
    // Pass control to whichever flavor of boot loader the board is configured
    // with.
    //
    SoftwareUpdateBegin(g_ui32SysClock);

    //
    // The previous function never returns but we need to stick in a return
    // code here to keep the compiler from generating a warning.
    //
    return(0);
}

And I also have a doubt is there any link between boot_demo_emac_rom  and boot_emac_flash projects and

bl_emac.c file

//*****************************************************************************
//
// bl_emac.c - Functions to update via Ethernet.
//
// Copyright (c) 2013-2020 Texas Instruments Incorporated.  All rights reserved.
// Software License Agreement
// 
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
// 
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
// 
// This is part of revision 2.2.0.295 of the Tiva Firmware Development Package.
//
//*****************************************************************************

#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "bl_config.h"
#include "inc/hw_emac.h"
#include "inc/hw_flash.h"
#include "inc/hw_gpio.h"
#include "inc/hw_memmap.h"
#include "inc/hw_nvic.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/emac.h"
#include "driverlib/sysctl.h"
#include "boot_loader/bl_decrypt.h"
#include "boot_loader/bl_flash.h"
#include "boot_loader/bl_hooks.h"
#include "driverlib/rom.h"
//
// Define ROM_SysCtlClockFreqSet() for snowflake RA0. Even though this function
// is deprecated in RA0 ROM, the function operates correctly when 
// SYSCTL_MOSCCTL register is configured correctly prior to calling this
// function.
//
#if defined(TARGET_IS_TM4C129_RA0)
#define ROM_SysCtlClockFreqSet                                                \
        ((uint32_t (*)(uint32_t ui32Config,                                   \
                       uint32_t ui32SysClock))ROM_SYSCTLTABLE[48])
#endif

//
// Define MAP_GPIOPadConfigSet() for the Boot Loader for Snowflake.
// This function fails in Snowflake for higher drive strengths, it will work
// properly for the instances where it is used here in the boot loader.
// 
#if defined(TARGET_IS_TM4C129_RA0) ||                                         \
    defined(TARGET_IS_TM4C129_RA1)
#define ROM_GPIOPadConfigSet                                                  \
        ((void (*)(uint32_t ui32Port,                                         \
                   uint8_t ui8Pins,                                           \
                   uint32_t ui32Strength,                                     \
                   uint32_t ui32PadType))ROM_GPIOTABLE[5])
#endif

//
// Define ROM_EMACInit for the bootloader of Snowflake RA0.  This function is
// deprecated in RA0 ROM, as it does not disable some interrupts that are not
// cleared by ***_EMACIntClear().  But that is not a problem for the bootloader
// as we are not enabling any interrupts.
//
#if defined(TARGET_IS_TM4C129_RA0)
#define ROM_EMACInit                                                          \
        ((void (*)(uint32_t ui32Base,                                         \
                   uint32_t ui32SysClk,                                       \
                   uint32_t ui32BusConfig,                                    \
                   uint32_t ui32RxBurst,                                      \
                   uint32_t ui32TxBurst,                                      \
                   uint32_t ui32DescSkipSize))ROM_EMACTABLE[8])
#endif

#include "driverlib/rom_map.h"

//*****************************************************************************
//
//! \addtogroup bl_emac_api
//! @{
//
//*****************************************************************************

#if defined(ENET_ENABLE_UPDATE) || defined(DOXYGEN)
//*****************************************************************************
//
// Make sure that the crystal frequency is defined.
//
//*****************************************************************************
#if !defined(CRYSTAL_FREQ)
#error ERROR: CRYSTAL_FREQ must be defined for Ethernet update!
#endif

//*****************************************************************************
//
// Make sure that boot loader update is not enabled (it is not supported via
// BOOTP given that there is no way to distinguish between a normal firmware
// image and a boot loader update image).
//
//*****************************************************************************
#if defined(ENABLE_BL_UPDATE)
#error ERROR: Updating the boot loader is not supported over Ethernet!
#endif

//*****************************************************************************
//
// TFTP packets contain 512 bytes of data and a packet shorter than this
// indicates the end of the transfer.
//
//*****************************************************************************
#define TFTP_BLOCK_SIZE         512

//*****************************************************************************
//
// uIP uses memset, so a simple one is provided here.  This is not as efficient
// as the one in the C library (from an execution time perspective), but it is
// much smaller.
//
//*****************************************************************************
void *
my_memset(void *pvDest, int iChar, size_t i32Length)
{
    int8_t *pi8Buf = (int8_t *)pvDest;

    //
    // Fill the buffer with the given character.
    //
    while(i32Length--)
    {
        *pi8Buf++ = iChar;
    }

    //
    // Return a pointer to the beginning of the buffer.
    //
    return(pvDest);
}

//*****************************************************************************
//
// uIP uses memcpy, so a simple one is provided here.  This is not as efficient
// as the one in the C library (from an execution time perspective), but it is
// much smaller.
//
//*****************************************************************************
void *
my_memcpy(void *pvDest, const void *pvSrc, size_t i32Length)
{
    const int8_t *pi8Src = (const int8_t *)pvSrc;
    int8_t *pi8Dest = (int8_t *)pvDest;

    //
    // Copy bytes from the source buffer to the destination buffer.
    //
    while(i32Length--)
    {
        *pi8Dest++ = *pi8Src++;
    }

    //
    // Return a pointer to the beginning of the destination buffer.
    //
    return(pvDest);
}

//*****************************************************************************
//
// Directly include the uIP code if using Ethernet for the update.  This allows
// non-Ethernet boot loader builds to not have to supply the uip-conf.h file
// that would otherwise be required.
//
//*****************************************************************************
#define memcpy my_memcpy
#define memset my_memset
#undef htonl
#undef ntohl
#undef htons
#undef ntohs
#include "third_party/uip-1.0/uip/pt.h"
#include "third_party/uip-1.0/uip/uip_arp.c"
#undef BUF
#include "third_party/uip-1.0/uip/uip.c"

//*****************************************************************************
//
// A prototype for the function (in the startup code) for a predictable length
// delay.
//
//*****************************************************************************
extern void Delay(uint32_t ui32Count);

//*****************************************************************************
//
// Defines for setting up the system clock.
//
//*****************************************************************************
#define SYSTICKHZ               100
#define SYSTICKMS               (1000 / SYSTICKHZ)

//*****************************************************************************
//
// UIP Timers (in ms)
//
//*****************************************************************************
#define UIP_PERIODIC_TIMER_MS   50
#define UIP_ARP_TIMER_MS        10000

//*****************************************************************************
//
// This structure defines the fields in a BOOTP request/reply packet.
//
//*****************************************************************************
typedef struct
{
    //
    // The operation; 1 is a request, 2 is a reply.
    //
    uint8_t ui8Op;

    //
    // The hardware type; 1 is Ethernet.
    //
    uint8_t ui8HType;

    //
    // The hardware address length; for Ethernet this will be 6, the length of
    // the MAC address.
    //
    uint8_t ui8HLen;

    //
    // Hop count, used by gateways for cross-gateway booting.
    //
    uint8_t ui8Hops;

    //
    // The transaction ID.
    //
    uint32_t ui32XID;

    //
    // The number of seconds elapsed since the client started trying to boot.
    //
    uint16_t ui16Secs;

    //
    // The BOOTP flags.
    //
    uint16_t ui16Flags;

    //
    // The client's IP address, if it knows it.
    //
    uint32_t ui32CIAddr;

    //
    // The client's IP address, as assigned by the BOOTP server.
    //
    uint32_t ui32YIAddr;

    //
    // The TFTP server's IP address.
    //
    uint32_t ui32SIAddr;

    //
    // The gateway IP address, if booting cross-gateway.
    //
    uint32_t ui32GIAddr;

    //
    // The hardware address; for Ethernet this is the MAC address.
    //
    uint8_t pui8CHAddr[16];

    //
    // The name, or nickname, of the server that should handle this BOOTP
    // request.
    //
    char pcSName[64];

    //
    // The name of the boot file to be loaded via TFTP.
    //
    char pcFile[128];

    //
    // Optional vendor-specific area; not used for BOOTP.
    //
    uint8_t pui8Vend[64];
}
tBOOTPPacket;

//*****************************************************************************
//
// The BOOTP commands.
//
//*****************************************************************************
#define BOOTP_REQUEST           1
#define BOOTP_REPLY             2

//*****************************************************************************
//
// The TFTP commands.
//
//*****************************************************************************
#define TFTP_RRQ                1
#define TFTP_WRQ                2
#define TFTP_DATA               3
#define TFTP_ACK                4
#define TFTP_ERROR              5

//*****************************************************************************
//
// The UDP ports used by the BOOTP protocol.
//
//*****************************************************************************
#define BOOTP_SERVER_PORT       67
#define BOOTP_CLIENT_PORT       68

//*****************************************************************************
//
// The UDP port for the TFTP server.
//
//*****************************************************************************
#define TFTP_PORT               69

//*****************************************************************************
//
// The MAC address of the Ethernet interface.
//
//*****************************************************************************
#ifdef ENET_MAC_ADDR0
static struct uip_eth_addr g_sMACAddr =
{
    {
        ENET_MAC_ADDR0,
        ENET_MAC_ADDR1,
        ENET_MAC_ADDR2,
        ENET_MAC_ADDR3,
        ENET_MAC_ADDR4,
        ENET_MAC_ADDR5
    }
};
#else
static struct uip_eth_addr g_sMACAddr;
#endif

//*****************************************************************************
//
// The number of SysTick interrupts since the start of the boot loader.
//
//*****************************************************************************
static uint32_t g_ui32Ticks;

//*****************************************************************************
//
// The seed for the random number generator.
//
//*****************************************************************************
static uint32_t g_ui32RandomSeed;

//*****************************************************************************
//
// The number of milliseconds since the last call to uip_udp_periodic().
//
//*****************************************************************************
static volatile uint32_t g_ui32PeriodicTimer;

//*****************************************************************************
//
// The number of milliseconds since the last call to uip_arp_timer().
//
//*****************************************************************************
static volatile uint32_t g_ui32ARPTimer;

//*****************************************************************************
//
// The transaction ID of the most recently sent out BOOTP request.
//
//*****************************************************************************
static uint32_t g_ui32XID;

//*****************************************************************************
//
// The state for the proto-thread that handles the BOOTP process.
//
//*****************************************************************************
static struct pt g_sThread;

//*****************************************************************************
//
// The amount of time to wait for a BOOTP reply before sending out a new BOOTP
// request.
//
//*****************************************************************************
static uint32_t g_ui32Delay;

//*****************************************************************************
//
// The target time (relative to g_ui32Ticks) when the next timeout occurs.
//
//*****************************************************************************
static uint32_t g_ui32Target;

//*****************************************************************************
//
// The IP address of the TFTP server.
//
//*****************************************************************************
static uip_ipaddr_t g_sServerAddr;

//*****************************************************************************
//
// The name of the file to be read from the TFTP server.
//
//*****************************************************************************
static char g_pcFilename[128];

//*****************************************************************************
//
// The end of flash.  If there is not a reserved block at the end of flash,
// this is the real end of flash.  If there is a reserved block, this is the
// start of the reserved block (i.e. the virtual end of flash).
//
//*****************************************************************************
static uint32_t g_ui32FlashEnd;

//*****************************************************************************
//
// The current block being read from the TFTP server.
//
//*****************************************************************************
static uint32_t g_ui32TFTPBlock;

//*****************************************************************************
//
// The number of TFTP retries.
//
//*****************************************************************************
static uint32_t g_ui32TFTPRetries;

//*****************************************************************************
//
// The UDP socket used to communicate with the BOOTP and TFTP servers (in
// sequence).
//
//*****************************************************************************
struct uip_udp_conn *g_pConn;

//*****************************************************************************
//
// The current link status.
//
//*****************************************************************************
static uint32_t g_ui32Link;

//*****************************************************************************
//
// Ethernet DMA descriptors.
//
// Although uIP uses a single buffer, the MAC hardware needs a minimum of
// 3 receive descriptors to operate.
//
//*****************************************************************************
#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.
//
//*****************************************************************************
#define RX_BUFFER_SIZE 1536
#define TX_BUFFER_SIZE 1536
uint8_t g_pui8RxBuffer[RX_BUFFER_SIZE];
uint8_t g_pui8TxBuffer[TX_BUFFER_SIZE];

//*****************************************************************************
//
//! Handles the SysTick interrupt.
//!
//! This function is called when the SysTick interrupt occurs.  It simply
//! keeps a running count of interrupts, used as a time basis for the BOOTP and
//! TFTP protocols.
//!
//! \return None.
//
//*****************************************************************************
void
SysTickIntHandler(void)
{
    //
    // Increment the tick count.
    //
    g_ui32Ticks++;
    g_ui32PeriodicTimer += SYSTICKMS;
    g_ui32ARPTimer += SYSTICKMS;
}

//*****************************************************************************
//
//! Computes a new random number.
//!
//! This function computes a new pseudo-random number, using a linear
//! congruence random number generator.  Note that if the entire 32-bits of the
//! produced random number are not being used, the upper N bits should be used
//! instead of the lower N bits as they are much more random (for example, use
//! ``RandomNumber() >> 28'' instead of ``RandomNumber() & 15'').
//!
//! \return Returns a 32-bit pseudo-random number.
//
//*****************************************************************************
static uint32_t
RandomNumber(void)
{
    //
    // Generate a new pseudo-random number with a linear congruence random
    // number generator.  This new random number becomes the seed for the next
    // random number.
    //
    g_ui32RandomSeed = (g_ui32RandomSeed * 1664525) + 1013904223;

    //
    // Return the new random number.
    //
    return(g_ui32RandomSeed);
}

//*****************************************************************************
//
// Read a packet from the DMA receive buffer into the uIP packet buffer.
//
//*****************************************************************************
static int32_t
PacketReceive(uint8_t *pui8Buf, int32_t i32BufLen)
{
    int_fast32_t i32FrameLen, i32Loop;

    //
    // By default, we assume we got a bad frame.
    //
    i32FrameLen = 0;

    //
    // See if the receive descriptor contains a valid frame.  Look for a
    // descriptor error, indicating that the incoming packet was truncated or,
    // if this is the last frame in a packet, the receive error bit.
    //
    if(!(g_psRxDescriptor[g_ui32RxDescIndex].ui32CtrlStatus &
         DES0_RX_STAT_ERR))
    {
        //
        // We have a valid frame so copy the content to the supplied buffer.
        // 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)
        {
            i32FrameLen =
                ((g_psRxDescriptor[g_ui32RxDescIndex].ui32CtrlStatus &
                  DES0_RX_STAT_FRAME_LENGTH_M) >>
                 DES0_RX_STAT_FRAME_LENGTH_S);

            //
            // Sanity check.  This shouldn't be required since we sized the uIP
            // buffer such that it's the same size as the DMA receive buffer
            // but, just in case...
            //
            if(i32FrameLen > i32BufLen)
            {
                i32FrameLen = i32BufLen;
            }

            //
            // Copy the data from the DMA receive buffer into the provided
            // frame buffer.
            //
            for(i32Loop = 0; i32Loop < i32FrameLen; i32Loop++)
            {
                pui8Buf[i32Loop] = g_pui8RxBuffer[i32Loop];
            }
        }
    }

    //
    // Move on to the next descriptor in the chain.
    //
    g_ui32RxDescIndex++;
    if(g_ui32RxDescIndex == NUM_RX_DESCRIPTORS)
    {
        g_ui32RxDescIndex = 0;
    }

    //
    // Mark the next descriptor in the ring as available for the receiver to
    // write into.
    //
    g_psRxDescriptor[g_ui32RxDescIndex].ui32CtrlStatus = DES0_RX_CTRL_OWN;

    //
    // Return the Frame Length
    //
    return(i32FrameLen);
}

//*****************************************************************************
//
// Transmit a packet from the supplied buffer.
//
//*****************************************************************************
static int32_t
PacketTransmit(uint8_t *pui8Buf, int32_t i32BufLen)
{
    int_fast32_t i32Loop;

    //
    // Wait for the previous packet to be transmitted.
    //
    while(g_psTxDescriptor[g_ui32TxDescIndex].ui32CtrlStatus &
          DES0_TX_CTRL_OWN)
    {
    }

    //
    // Check that we're not going to overflow the transmit buffer.  This
    // shouldn't be necessary since the uIP buffer is smaller than our DMA
    // transmit buffer but, just in case...
    //
    if(i32BufLen > TX_BUFFER_SIZE)
    {
        i32BufLen = TX_BUFFER_SIZE;
    }

    //
    // Copy the packet data into the transmit buffer.
    //
    for(i32Loop = 0; i32Loop < i32BufLen; i32Loop++)
    {
        g_pui8TxBuffer[i32Loop] = pui8Buf[i32Loop];
    }

    //
    // Move to the next descriptor.
    //
    g_ui32TxDescIndex++;
    if(g_ui32TxDescIndex == NUM_TX_DESCRIPTORS)
    {
        g_ui32TxDescIndex = 0;
    }

    //
    // Fill in the packet size and tell the transmitter to start work.
    //
    g_psTxDescriptor[g_ui32TxDescIndex].ui32Count = (uint32_t)i32BufLen;
    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.
    //
    ROM_EMACTxDMAPollDemand(EMAC0_BASE);

    //
    // Return the number of bytes sent.
    //
    return(i32BufLen);
}

//*****************************************************************************
//
//! Constructs and sends a BOOTP request packet.
//!
//! This function constructs a BOOTP request packet and sends it as a broadcast
//! message to the network.
//!
//! \return None.
//
//*****************************************************************************
static void
SendBOOTPRequest(void)
{
    uint8_t *pui8Packet = (uint8_t *)uip_appdata;
    tBOOTPPacket *psBOOTP = (tBOOTPPacket *)uip_appdata;
    uint32_t ui32Idx;

    //
    // Zero fill the BOOTP request packet.
    //
    for(ui32Idx = 0; ui32Idx < sizeof(tBOOTPPacket); ui32Idx++)
    {
        pui8Packet[ui32Idx] = 0;
    }

    //
    // Construct a BOOTP request.
    //
    psBOOTP->ui8Op = BOOTP_REQUEST;

    //
    // Set the hardware type to Ethernet.
    //
    psBOOTP->ui8HType = 0x01;

    //
    // Set the hardware address length to 6.
    //
    psBOOTP->ui8HLen = 0x06;

    //
    // Choose a random number for the transaction ID.
    //
    psBOOTP->ui32XID = g_ui32XID = RandomNumber();

    //
    // Set the number of seconds since we started.
    //
    psBOOTP->ui16Secs = HTONS(g_ui32Ticks / SYSTICKHZ);

    //
    // Fill in the Ethernet MAC address.
    //
    for(ui32Idx = 0; ui32Idx < 6; ui32Idx++)
    {
        psBOOTP->pui8CHAddr[ui32Idx] = g_sMACAddr.addr[ui32Idx];
    }

    //
    // Set the server name if defined.
    //
#ifdef ENET_BOOTP_SERVER
    for(ui32Idx = 0;
        (psBOOTP->pcSName[ui32Idx] = ENET_BOOTP_SERVER[ui32Idx]) != 0;
        ui32Idx++)
    {
    }
#endif

    //
    // Send the BOOTP request packet.
    //
    uip_udp_send(sizeof(tBOOTPPacket));
}

//*****************************************************************************
//
//! Parses a packet checking for a BOOTP reply message.
//!
//! This function parses a packet to determine if it is a BOOTP reply to our
//! currently outstanding BOOTP request.  If a valid reply is found, the
//! appropriate information from the packet is extracted and saved.
//!
//! \return Returns 1 if a valid BOOTP reply message was found and 0 otherwise.
//
//*****************************************************************************
static uint32_t
ParseBOOTPReply(void)
{
    tBOOTPPacket *psBOOTP = (tBOOTPPacket *)uip_appdata;
    uint32_t ui32Idx;

    //
    // See if this is a reply for our current BOOTP request.
    //
    if((psBOOTP->ui8Op != BOOTP_REPLY) ||
       (psBOOTP->ui32XID != g_ui32XID) ||
       (*(uint32_t *)psBOOTP->pui8CHAddr != *(uint32_t *)g_sMACAddr.addr) ||
       (*(uint16_t *)(psBOOTP->pui8CHAddr + 4) !=
        *(uint16_t *)(g_sMACAddr.addr + 4)))
    {
        return(0);
    }

    //
    // Extract our IP address from the response.
    //
    *((uint32_t *)(void *)(&uip_hostaddr)) = psBOOTP->ui32YIAddr;

    //
    // Extract the server address from the response.
    //
    *((uint32_t *)(void *)(&g_sServerAddr)) = psBOOTP->ui32SIAddr;

    //
    // Save the boot file name.
    //
    for(ui32Idx = 0;
        ((g_pcFilename[ui32Idx] = psBOOTP->pcFile[ui32Idx]) != 0) &&
        (ui32Idx < (sizeof(g_pcFilename) - 1));
        ui32Idx++)
    {
    }
    g_pcFilename[ui32Idx] = 0;

    //
    // A valid BOOTP reply was found and decoded.
    //
    return(1);
}


//*****************************************************************************
//
//! Constructs and sends a TFTP error packet.
//!
//! This function constructs a TFTP read request packet (RRQ) and sends it to
//! the server.
//!
//! \return None.
//
//*****************************************************************************
static void
SendTFTPError(uint16_t ui16Error, char *pcString)
{
    uint8_t *pui8Packet = (uint8_t *)uip_appdata;
    int32_t i32Len;

    pui8Packet[0] = (TFTP_ERROR >> 8) & 0xff;
    pui8Packet[1] = TFTP_ERROR & 0xff;
    pui8Packet[2] = (ui16Error >> 8) & 0xFF;
    pui8Packet[3] = ui16Error & 0xFF;

    //
    // Get ready to copy the error string.
    //
    i32Len = 4;
    pui8Packet += 4;

    //
    // Copy as much of the string as we can fit.
    //
    while((i32Len < (UIP_APPDATA_SIZE - 1)) && *pcString)
    {
        *pui8Packet++ = *pcString++;
        i32Len++;
    }

    //
    // Write the terminating 0.
    //
    *pui8Packet = (uint8_t)0;

    //
    // Send the error packet.
    //
    uip_udp_send(i32Len + 1);
}

//*****************************************************************************
//
//! Constructs and sends a TFTP read packet.
//!
//! This function constructs a TFTP read request packet (RRQ) and sends it to
//! the server.
//!
//! \return None.
//
//*****************************************************************************
static void
SendTFTPGet(void)
{
    uint8_t *pui8Packet = (uint8_t *)uip_appdata;
    uint32_t ui32Idx;
    char *pcFilename;

    //
    // The TFTP RRQ packet should be sent to the TFTP server port.
    //
    g_pConn->rport = HTONS(TFTP_PORT);

    //
    // Set the TFTP packet opcode to RRQ.
    //
    pui8Packet[0] = (TFTP_RRQ >> 8) & 0xff;
    pui8Packet[1] = TFTP_RRQ & 0xff;

    //
    // Copy the file name into the RRQ packet.
    //
    for(ui32Idx = 2, pcFilename = g_pcFilename;
        (pui8Packet[ui32Idx++] = *pcFilename++) != 0; )
    {
    }

    //
    // Set the transfer mode to binary.
    //
    for(pcFilename = "octet"; (pui8Packet[ui32Idx++] = *pcFilename++) != 0; )
    {
    }

    //
    // Send the TFTP read packet.
    //
    uip_udp_send(ui32Idx);
}

//*****************************************************************************
//
//! Parses a packet checking for a TFTP data packet.
//!
//! This function parses a packet to determine if it is a TFTP data packet for
//! a current TFTP transfer.  If a valid packet is found, the contents of the
//! packet are programmed into flash.
//!
//! \return Returns 1 if this packet was the last packet of the TFTP data
//! transfer and 0 otherwise.
//
//*****************************************************************************
static uint32_t
ParseTFTPData(void)
{
    uint8_t *pui8Packet = (uint8_t *)uip_appdata;
    uint32_t ui32FlashAddr;
    uint32_t ui32Idx;

    //
    // See if this is a TFTP data packet.
    //
    if((pui8Packet[0] != ((TFTP_DATA >> 8) && 0xff)) ||
       (pui8Packet[1] != (TFTP_DATA & 0xff)))
    {
        return(0);
    }

    //
    // If the remote port on our connection is still the TFTP server port (i.e.
    // this is the first data packet), then copy the transaction ID for the
    // TFTP data connection into our connection.  This will ensure that our
    // response will be sent to the correct port.
    //
    if(g_pConn->rport == HTONS(TFTP_PORT))
    {
        g_pConn->rport =
            ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])->srcport;
    }

    //
    // See if this is the correct data packet.
    //
    if((pui8Packet[2] != ((g_ui32TFTPBlock >> 8) & 0xff)) ||
       (pui8Packet[3] != (g_ui32TFTPBlock & 0xff)))
    {
        //
        // Since the wrong data packet was sent, resend the ACK for it since
        // we've already processed it.
        //
        pui8Packet[0] = (TFTP_ACK >> 8) & 0xff;
        pui8Packet[1] = TFTP_ACK & 0xff;
        uip_udp_send(4);

        //
        // Ignore this packet.
        //
        return(0);
    }

    //
    // What address are we about to program to?
    //
    ui32FlashAddr =
        ((g_ui32TFTPBlock - 1) * TFTP_BLOCK_SIZE) + APP_START_ADDRESS;

    //
    // Do not program this data into flash if it is beyond the end of flash.
    //
    if(ui32FlashAddr < g_ui32FlashEnd)
    {
        //
        // If this is the first block and we have been provided with a start
        // hook function, call it here to indicate that we are about to begin
        // flashing a new image.
        //
#ifdef BL_START_FN_HOOK
        if(g_ui32TFTPBlock == 1)
        {
            BL_START_FN_HOOK();
        }
#endif

        //
        // Clear any flash error indicator.
        //
        BL_FLASH_CL_ERR_FN_HOOK();

        //
        // If this is the first data packet and code protection is enabled,
        // then erase the entire flash.
        //
#ifdef FLASH_CODE_PROTECTION
        if(g_ui32TFTPBlock == 1)
        {
            //
            // Loop through the pages in the flash, excluding the pages that
            // contain the boot loader and the optional reserved space.
            //
            for(ui32Idx = APP_START_ADDRESS; ui32Idx < g_ui32FlashEnd;
                ui32Idx += FLASH_PAGE_SIZE)
            {
                //
                // Erase this block of the flash.
                //
                BL_FLASH_ERASE_FN_HOOK((ui32Idx);
            }
        }
#else
        //
        // Flash code protection is not enabled, so see if the data in this
        // packet will be programmed to the beginning of a flash block.  We
        // assume that the flash block size is always a multiple of 1KB so,
        // since each TFTP packet is 512 bytes and that the start must always
        // be on a flash page boundary, we can be sure that we will hit the
        // start of each page as we receive packets.
        //
        if(!(ui32FlashAddr & (FLASH_PAGE_SIZE - 1)))
        {
            //
            // Erase this block of the flash.
            //
            BL_FLASH_ERASE_FN_HOOK(ui32FlashAddr);
        }
#endif

        //
        // Decrypt the data if required.
        //
#ifdef BL_DECRYPT_FN_HOOK
        BL_DECRYPT_FN_HOOK(pui8Packet + 4, uip_len - 4);
#endif

        //
        // Program this block of data into flash.
        //
        BL_FLASH_PROGRAM_FN_HOOK(ui32FlashAddr, (pui8Packet + 4),
                                 (uip_len - 4));

        //
        // If a progress reporting hook function has been provided, call it
        // here.  The TFTP protocol doesn't let us know how large the image is
        // before it starts the transfer so we pass 0 as the ui32Total
        // parameter to indicate this.
        //
#ifdef BL_PROGRESS_FN_HOOK
        BL_PROGRESS_FN_HOOK(((ui32FlashAddr - APP_START_ADDRESS) +
                             (uip_len - 4)), 0);
#endif
    }

    //
    // Increment to the next block.
    //
    g_ui32TFTPBlock++;

    //
    // Save the packet length.
    //
    ui32Idx = uip_len;

    //
    // Did we see any error?
    //
    if(BL_FLASH_ERROR_FN_HOOK())
    {
        //
        // Yes - send back an error packet.
        //
        SendTFTPError(2, "Error programming flash.");
    }
    else
    {
        //
        // No errors reported so construct an ACK packet.  The block number
        // field is already correct, so it does not need to be set.
        //
        pui8Packet[0] = (TFTP_ACK >> 8) & 0xff;
        pui8Packet[1] = TFTP_ACK & 0xff;

        //
        // Send the ACK packet to the TFTP server.
        //
        uip_udp_send(4);
    }

    //
    // If the packet was shorter than TFTP_BLOCK_SIZE bytes then this was the
    // last packet in the file.
    //
    if(ui32Idx != (TFTP_BLOCK_SIZE + 4))
    {
        //
        // If an end signal hook function has been provided, call it here.
        //
#ifdef BL_END_FN_HOOK
        BL_END_FN_HOOK();
#endif
        return(1);
    }
    //
    // There is more data to be read.
    //
    return(0);
}

uint16_t
LOCAL_EMACPHYRead(uint32_t ui32Base, uint8_t ui8PhyAddr, uint8_t ui8RegAddr)
{

    //
    // Make sure the MII is idle.
    //
    while(HWREG(ui32Base + EMAC_O_MIIADDR) & EMAC_MIIADDR_MIIB)
    {
    }

    //
    // Tell the MAC to read the given PHY register.
    //
    HWREG(ui32Base + EMAC_O_MIIADDR) =
        ((HWREG(ui32Base + EMAC_O_MIIADDR) & EMAC_MIIADDR_CR_M) |
         (ui8RegAddr << EMAC_MIIADDR_MII_S) |
         (ui8PhyAddr << EMAC_MIIADDR_PLA_S) | EMAC_MIIADDR_MIIB);

    //
    // Wait for the read to complete.
    //
    while(HWREG(ui32Base + EMAC_O_MIIADDR) & EMAC_MIIADDR_MIIB)
    {
    }

    //
    // Return the result.
    //
    return(HWREG(ui32Base + EMAC_O_MIIDATA) & EMAC_MIIDATA_DATA_M);
}

//*****************************************************************************
//
//! Handles the BOOTP process.
//!
//! This function contains the proto-thread for handling the BOOTP process.  It
//! first communicates with the BOOTP server to get its boot parameters (IP
//! address, server address, and file name), then it communicates with the TFTP
//! server on the specified server to read the firmware image file.
//!
//! \return None.
//
//*****************************************************************************
#ifdef DOXYGEN
char
BOOTPThread(void)
#else
PT_THREAD(BOOTPThread(void))
#endif
{
    //
    // Begin the proto-thread.
    //
    PT_BEGIN(&g_sThread);

wait_for_link:
    PT_WAIT_UNTIL(&g_sThread,
                  (LOCAL_EMACPHYRead(EMAC0_BASE, 0, EPHY_BMSR) &
                   EPHY_BMSR_LINKSTAT) != 0);

    //
    // Reset the host address.
    //
    *((uint32_t *)(void *)(&uip_hostaddr)) = 0;

    //
    // Re-bind the UDP socket for sending requests to the BOOTP server.
    //
    uip_udp_remove(g_pConn);
    *((uint32_t *)(void *)(&g_sServerAddr)) = 0xffffffff;
    uip_udp_new(&g_sServerAddr, HTONS(BOOTP_SERVER_PORT));
    uip_udp_bind(g_pConn, HTONS(BOOTP_CLIENT_PORT));

    //
    // Set the initial delay between BOOTP requests to 1 second.
    //
    g_ui32Delay = SYSTICKHZ;

    //
    // Loop forever.  This loop is explicitly exited when a valid BOOTP reply
    // is received.
    //
    while(1)
    {
        //
        // Send a BOOTP request.
        //
        SendBOOTPRequest();

        //
        // Set the amount of time to wait for the BOOTP reply message.
        //
        g_ui32Target = g_ui32Ticks + g_ui32Delay;

        //
        // Wait until a packet is received or the timeout has occurred.
        //
wait_for_bootp_reply:
        PT_WAIT_UNTIL(&g_sThread,
                      ((g_ui32Link = (LOCAL_EMACPHYRead(EMAC0_BASE, 0, EPHY_BMSR) &
                                      EPHY_BMSR_LINKSTAT)) == 0) ||
                      uip_newdata() || (g_ui32Ticks > g_ui32Target));

        //
        // If the link has been lost, go back to waiting for a link.
        //
        if(g_ui32Link == 0)
        {
            goto wait_for_link;
        }
                      
        //
        // See if a packet has been received.
        //
        if(uip_newdata())
        {
            //
            // Clear the new data flag so that this packet will only be
            // examined one time.
            //
            uip_flags &= ~(UIP_NEWDATA);

            //
            // See if this is a BOOTP reply.
            //
            if(ParseBOOTPReply() == 1)
            {
                break;
            }

            //
            // This was not a BOOTP reply packet, so go back to waiting.
            //
            goto wait_for_bootp_reply;
        }

        //
        // If the delay between BOOTP requests is less than 60 seconds, double
        // the delay time.  This avoids constantly slamming the network with
        // requests.
        //
        if(g_ui32Delay < (60 * SYSTICKHZ))
        {
            g_ui32Delay *= 2;
        }
    }

    //
    // Reconfigure the UDP socket to target the TFTP port on the server.
    //
    uip_ipaddr_copy(&g_pConn->ripaddr, g_sServerAddr);
    uip_udp_bind(g_pConn, HTONS(13633));

    //
    // Send a TFTP read request.
    //
    SendTFTPGet();

    //
    // Since the first TFTP read request will result in an ARP request, delay
    // for just a bit and then re-issue the TFTP read request.
    //
    PT_YIELD(&g_sThread);

    //
    // Resend the TFTP read request.  If the ARP request has already been
    // answered, this will go out as is and avoid the two second timeout below.
    //
    SendTFTPGet();

    //
    // Start the TFTP transfer from block one.
    //
    g_ui32TFTPBlock = 1;

    //
    // Set the number of TFTP retries to zero.
    //
    g_ui32TFTPRetries = 0;

    //
    // Loop forever.  This loop is explicitly exited when the TFTP transfer has
    // completed.
    //
    while(1)
    {
        //
        // Set the amount of time to wait for the TFTP data packet.
        //
        g_ui32Target = g_ui32Ticks + (SYSTICKHZ * 4);

        //
        // Wait until a packet is received or the timeout has occurred.
        //
        PT_WAIT_UNTIL(&g_sThread,
                      ((g_ui32Link = (LOCAL_EMACPHYRead(EMAC0_BASE, 0, EPHY_BMSR) &
                                      EPHY_BMSR_LINKSTAT)) == 0) ||
                      uip_newdata() || (g_ui32Ticks > g_ui32Target));

        //
        // If the link has been lost, go back to waiting for a link.
        //
        if(g_ui32Link == 0)
        {
            goto wait_for_link;
        }
                      
        //
        // See if a packet has been received.
        //
        if(uip_newdata())
        {
            //
            // Clear the new data flag so that this packet will only be
            // examined one time.
            //
            uip_flags &= ~(UIP_NEWDATA);

            //
            // See if this is a TFTP data packet.
            //
            if(ParseTFTPData() == 1)
            {
                break;
            }
        }
        else if(g_ui32TFTPRetries < 3)
        {
            //
            // The transfer timed out, so send a new TFTP read request.
            //
            SendTFTPGet();

            //
            // Start the TFTP transfer from block one.
            //
            g_ui32TFTPBlock = 1;

            //
            // Increment the count of TFTP retries.
            //
            g_ui32TFTPRetries++;
        }
        else
        {
            //
            // The TFTP transfer failed after three retries, so start over.
            //
            goto wait_for_link;
        }
    }
    //
    // Wait for the last packet to be transmitted.
    //
    while(g_psTxDescriptor[g_ui32TxDescIndex].ui32CtrlStatus &
          DES0_TX_CTRL_OWN)
    {
    }

    //
    // Wait for a bit to make sure that the final ACK packet is transmitted.
    //
    g_ui32Target = g_ui32Ticks + (SYSTICKHZ / 4);
    while(g_ui32Ticks < g_ui32Target)
    {
        PT_YIELD(&g_sThread);
    }

    //
    // Perform a software reset request.  This will cause the microcontroller
    // to reset; no further code will be executed.
    //
    HWREG(NVIC_APINT) = NVIC_APINT_VECTKEY | NVIC_APINT_SYSRESETREQ;

    //
    // The microcontroller should have reset, so this should never be reached.
    // Just in case, loop forever.
    //
    while(1)
    {
    }

    //
    // End the proto-thread.
    //
    PT_END(&g_sThread);
}

static void
LOCAL_EMACPHYConfigSet(uint32_t ui32Base, uint32_t ui32Config)
{
    //
    // Write the Ethernet PHY configuration to the peripheral configuration
    // register.
    //
    HWREG(ui32Base + EMAC_O_PC) = ui32Config;

    //
    // If using the internal PHY, reset it to ensure that new configuration is
    // latched there.
    //
    if((ui32Config & EMAC_PHY_TYPE_MASK) == EMAC_PHY_TYPE_INTERNAL)
    {
        ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_EPHY0);
        while(!ROM_SysCtlPeripheralReady(SYSCTL_PERIPH_EPHY0))
        {
            //
            // Wait for the PHY reset to complete.
            //
        }

        //
        // Delay a bit longer to ensure that the PHY reset has completed.
        //
        ROM_SysCtlDelay(1000);
    }

    //
    // If using an external RMII PHY, we must set 2 bits in the Ethernet MAC
    // Clock Configuration Register.
    //
    if((ui32Config & EMAC_PHY_TYPE_MASK) == EMAC_PHY_TYPE_EXTERNAL_RMII)
    {
        //
        // Select and enable the external clock from the RMII PHY.
        //
        HWREG(EMAC0_BASE + EMAC_O_CC) |= EMAC_CC_CLKEN;
    }
    else
    {
        //
        // Disable the external clock.
        //
        HWREG(EMAC0_BASE + EMAC_O_CC) &= ~EMAC_CC_CLKEN;
    }

    //
    // Reset the MAC regardless of whether the PHY connection changed or not.
    //
    ROM_EMACReset(EMAC0_BASE);

    ROM_SysCtlDelay(1000);
}

//*****************************************************************************
//
//! Reconfigures the Ethernet controller.
//!
//! \param ui32Clock is the system clock frequency.
//!
//! This function reconfigures the Ethernet controller, preparing it for use by
//! the boot loader.  This performs the steps common between the direct
//! invocation of the boot loader and the application invocation of the boot
//! loader.
//!
//! \return None.
//
//*****************************************************************************
void
EnetReconfig(uint32_t ui32Clock)
{
    uip_ipaddr_t sAddr;
    uint32_t ui32Loop;
    uint32_t ui32User0, ui32User1;

    //
    // Configure for use with the internal PHY.
    //
    LOCAL_EMACPHYConfigSet(EMAC0_BASE,
                           (EMAC_PHY_TYPE_INTERNAL | EMAC_PHY_INT_MDIX_EN |
                            EMAC_PHY_AN_100B_T_FULL_DUPLEX));
    

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

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

    //
    // Get the MAC address from the flash user registers.  If it has not been
    // programmed, then use the boot loader default MAC address.
    //
    ROM_FlashUserGet(&ui32User0, &ui32User1);
    if((ui32User0 == 0xffffffff) || (ui32User1 == 0xffffffff))
    {
        //
        // MAC address has not been programmed, use default.
        //
        g_sMACAddr.addr[0] = 0x00;
        g_sMACAddr.addr[1] = 0x1a;
        g_sMACAddr.addr[2] = 0xb6;
        g_sMACAddr.addr[3] = 0x00;
        g_sMACAddr.addr[4] = 0x64;
        g_sMACAddr.addr[5] = 0x00;
    }
    else
    {
        g_sMACAddr.addr[0] = ui32User0 & 0xff;
        g_sMACAddr.addr[1] = (ui32User0 >> 8) & 0xff;
        g_sMACAddr.addr[2] = (ui32User0 >> 16) & 0xff;
        g_sMACAddr.addr[3] = ui32User1 & 0xff;
        g_sMACAddr.addr[4] = (ui32User1 >> 8) & 0xff;
        g_sMACAddr.addr[5] = (ui32User1 >> 16) & 0xff;
    }

    //
    // Set MAC configuration options.
    //
    ROM_EMACConfigSet(EMAC0_BASE,
                  (EMAC_CONFIG_FULL_DUPLEX | 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 each of the transmit descriptors.  Note that we leave 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 |
             (TX_BUFFER_SIZE << DES1_TX_CTRL_BUFF1_SIZE_S));
        g_psTxDescriptor[ui32Loop].pvBuffer1 = g_pui8TxBuffer;
        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_pui8RxBuffer;
        g_psRxDescriptor[ui32Loop].DES3.pLink =
            (ui32Loop == (NUM_RX_DESCRIPTORS - 1)) ?
            g_psRxDescriptor : &g_psRxDescriptor[ui32Loop + 1];
    }

    //
    // Set the descriptor pointers in the hardware.
    //
    ROM_EMACRxDMADescriptorListSet(EMAC0_BASE, g_psRxDescriptor);
    ROM_EMACTxDMADescriptorListSet(EMAC0_BASE, 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;

    //
    // Program the MAC address.
    //
    ROM_EMACAddrSet(EMAC0_BASE, 0, g_sMACAddr.addr);

    //
    // Wait for the link to become active.
    //
    while((ROM_EMACPHYRead(EMAC0_BASE, 0, EPHY_BMSR) &
           EPHY_BMSR_LINKSTAT) == 0)
    {
    }

    //
    // Set MAC filtering options.  We receive all broadcast and multicast
    // packets along with those addressed specifically for us.
    //
    ROM_EMACFrameFilterSet(EMAC0_BASE, (EMAC_FRMFILTER_SADDR |
                                    EMAC_FRMFILTER_PASS_MULTICAST |
                                    EMAC_FRMFILTER_PASS_NO_CTRL));

    //
    // Seed the random number generator from the MAC address.
    //
    g_ui32RandomSeed = *(uint32_t *)(g_sMACAddr.addr + 2);

    //
    // Initialize the uIP stack.
    //
    uip_init();
    uip_arp_init();

    //
    // Set the MAC address.
    //
    uip_setethaddr(g_sMACAddr);

    //
    // Initialize the proto-thread used by the BOOTP protocol handler.
    //
    PT_INIT(&g_sThread);

    //
    // Create a UDP socket for sending requests to the BOOTP server.  After the
    // BOOTP portion of the protocol has been handled, this socket will be
    // reused to communicate with the TFTP server.
    //
    *((uint32_t *)(void *)(&sAddr)) = 0xffffffff;
    g_pConn = uip_udp_new(&sAddr, HTONS(BOOTP_SERVER_PORT));
    uip_udp_bind(g_pConn, HTONS(BOOTP_CLIENT_PORT));

    //
    // Enable the Ethernet MAC transmitter and receiver.
    //
    ROM_EMACTxEnable(EMAC0_BASE);
    ROM_EMACRxEnable(EMAC0_BASE);

    //
    // Mark the first receive descriptor as available to the DMA to start
    // the receive processing.
    //
    g_psRxDescriptor[g_ui32RxDescIndex].ui32CtrlStatus |= DES0_RX_CTRL_OWN;

    //
    // Reset the counters that are incremented by SysTick.
    //
    g_ui32Ticks = 0;
    g_ui32PeriodicTimer = 0;
    g_ui32ARPTimer = 0;

    //
    // Setup SysTick.
    //
    HWREG(NVIC_ST_RELOAD) = (ui32Clock / SYSTICKHZ) - 1;
    HWREG(NVIC_ST_CTRL) = (NVIC_ST_CTRL_CLK_SRC | NVIC_ST_CTRL_INTEN |
                           NVIC_ST_CTRL_ENABLE);
}
//*****************************************************************************
//
//! Configures the Ethernet controller.
//!
//! This function configures the Ethernet controller, preparing it for use by
//! the boot loader.
//!
//! \return None.
//
//*****************************************************************************
void
ConfigureEnet(void)
{
    //
    // Make sure the main oscillator is enabled because this is required by
    // the PHY.  The system must have a 25MHz crystal attached to the OSC
    // pins.  The SYSCTL_MOSC_HIGHFREQ parameter is used when the crystal
    // frequency is 10MHz or higher.
    //
    HWREG(SYSCTL_MOSCCTL) = SYSCTL_MOSC_HIGHFREQ;

    //
    // Delay while the main oscillator starts up.
    //
    Delay(5242880);

    MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                            SYSCTL_OSC_MAIN |
                            SYSCTL_USE_PLL |
                            SYSCTL_CFG_VCO_480), 120000000);


#ifdef ENET_ENABLE_LEDS
    //
    // PF1/PK4/PK6 are used for Ethernet LEDs.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK);
    ROM_GPIOPinConfigure(GPIO_PF1_EN0LED2);
    ROM_GPIOPinConfigure(GPIO_PK4_EN0LED0);
    ROM_GPIOPinConfigure(GPIO_PK6_EN0LED1);

    //
    // Make the pin(s) be peripheral controlled.
    //
    ROM_GPIODirModeSet(GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_DIR_MODE_HW);
    ROM_GPIODirModeSet(GPIO_PORTK_BASE, GPIO_PIN_4|GPIO_PIN_6, GPIO_DIR_MODE_HW);

    //
    // Set the pad(s) for standard push-pull operation.
    //
    ROM_GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD);
    ROM_GPIOPadConfigSet(GPIO_PORTK_BASE, GPIO_PIN_4|GPIO_PIN_6, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD);
#endif

    //
    // Enable and reset the Ethernet modules.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_EMAC0);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_EPHY0);
    ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_EMAC0);
    ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_EPHY0);

    while(!ROM_SysCtlPeripheralReady(SYSCTL_PERIPH_EMAC0))
    {
    }

}

//*****************************************************************************
//
//! Starts the update process via BOOTP.
//!
//! This function starts the Ethernet firmware update process.  The BOOTP
//! (as defined by RFC951 at http://tools.ietf.org/html/rfc951) and TFTP (as
//! defined by RFC1350 at http://tools.ietf.org/html/rfc1350) protocols are
//! used to transfer the firmware image over Ethernet.
//!
//! \return Never returns.
//
//*****************************************************************************
void
UpdateBOOTP(void)
{
    //
    // Get the size of flash.
    //
    g_ui32FlashEnd =  ROM_SysCtlFlashSizeGet();
#ifdef FLASH_RSVD_SPACE
    g_ui32FlashEnd -= FLASH_RSVD_SPACE;
#endif

    //
    // Perform the common Ethernet configuration. The frequency should
    // match whatever the application sets the system clock.
    //
    EnetReconfig(120000000);

    //
    // Main Application Loop.
    //
    while(1)
    {
        uint32_t ui32Temp;

        //
        // See if there is a packet waiting to be read.
        //
        if(!(g_psRxDescriptor[g_ui32RxDescIndex].ui32CtrlStatus &
             DES0_RX_CTRL_OWN))
        {
            //
            // Read the packet from the Ethernet controller.
            //
            uip_len = PacketReceive(uip_buf, UIP_CONF_BUFFER_SIZE);

            //
            // See if this is an IP packet.
            //
            if((uip_len != 0) &&
               (((struct uip_eth_hdr *)&uip_buf[0])->type ==
                HTONS(UIP_ETHTYPE_IP)))
            {
                //
                // Update the ARP tables based on this packet.
                //
                uip_arp_ipin();

                //
                // Process this packet.
                //
                uip_input();

                //
                // See if the processing of this packet resulted in a packet to be
                // sent.
                //
                if(uip_len > 0)
                {
                    //
                    // Update the ARP tables based on the packet to be sent.
                    //
                    uip_arp_out();

                    //
                    // Send the packet.
                    //
                    PacketTransmit(uip_buf, uip_len);

                    //
                    // Indicate that the packet has been sent.
                    //
                    uip_len = 0;
                }
            }

            //
            // See if this is an ARP packet.
            //
            else if((uip_len != 0) &&
                    (((struct uip_eth_hdr *)&uip_buf[0])->type ==
                     HTONS(UIP_ETHTYPE_ARP)))
            {
                //
                // Process this packet.
                //
                uip_arp_arpin();

                //
                // See if the processing of this packet resulted in a packet to be
                // sent.
                //
                if(uip_len > 0)
                {
                    //
                    // Send the packet.
                    //
                    PacketTransmit(uip_buf, uip_len);

                    //
                    // Indicate that the packet has been sent.
                    //
                    uip_len = 0;
                }
            }
        }

        //
        // See if the periodic timer has expired.
        //
        if(g_ui32PeriodicTimer > UIP_PERIODIC_TIMER_MS)
        {
            //
            // Reset the periodic timer.
            //
            g_ui32PeriodicTimer = 0;

            //
            // Loop through the UDP connections.
            //
            for(ui32Temp = 0; ui32Temp < UIP_UDP_CONNS; ui32Temp++)
            {
                //
                // Perform the periodic processing on this UDP connection.
                //
                uip_udp_periodic(ui32Temp);

                //
                // See if the periodic processing of this connection resulted in a
                // packet to be sent.
                //
                if(uip_len > 0)
                {
                    //
                    // Update the ARP tables based on the packet to be sent.
                    //
                    uip_arp_out();

                    //
                    // Send the packet.
                    //
                    PacketTransmit(uip_buf, uip_len);

                    //
                    // Indicate that the packet has been sent.
                    //
                    uip_len = 0;
                }
            }
        }

        //
        // See if the ARP timer has expired.
        //
        if(g_ui32ARPTimer > UIP_ARP_TIMER_MS)
        {
            //
            // Reset the ARP timer.
            //
            g_ui32ARPTimer = 0;

            //
            // Perform periodic processing on the ARP table.
            //
            uip_arp_timer();
        }
    }
}

//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************
#endif
 

Please help to sort this issue ASAP 

  • Another doubt is how ROM_UpdateEMAC() this function is working ?

  • Hi team i aslo try to run boot_emac_flash but iam strcuk here

     

    I dont know what to do can you help me 

    this is the configuration I made

  • I trying to do firmware upgrade using ethernet bootloader code (boot_demo_emac_rom)(TM4C1294NCPDT),
    The problem is I could not extract the payload that is Hex File DATA in the boot_demo_emac_rom code (swupdate.c file)

    This is using the ROM-based bootloader. In another word, the bootloader is stored in the ROM. I strongly suggest you go through Booloader User's guide the understand the difference between the ROM-based bootloader vs. the flash-based bootloader. https://www.ti.com/lit/pdf/spmu301

    When you run the ROM bootloader, it does NOT execute functions in swupdate.c. When the applications calls ROM_UpdateEMAC(), it jumps to the bootloader code in the ROM. 

    If you need to modify the bootloader as to perform some custom algorithm like encryption or decryption, you would need to run the flash-based bootloader. 

    Another doubt is how ROM_UpdateEMAC() this function is working ?

    As explained above. 

    i aslo try to run boot_emac_flash but iam strcuk here

     

    The  boot_emac_flash is the flash-based bootloader. The bootloader must be first loaded to the flash through the JTAG interface just like any programs such as blinky or hello. Once it is running, it will send out a BOOTP request to the Boot and TFTP server and that is the PC which is running the LM flash programmer. The flash-based bootloader (boot_emac_flash) go along with an example application (boot_demo_emac_flash). The boot_emac_flash and load the boot_demo_emac_flash through the Ethernet port. 

    See below steps to run the flash-based example. 

    Step1: Run the enet_lwip or enet_io to obtain the IP address.  On the terminal window you should see the IP address printed out. Record this address. 

     Step2: Load the boot_emac_flash via the JTAG interface using CCS. This is the bootloader to be loaded at 0x0. 

     Step 3. Bring up the LM flash programmer. See below image. Provide the IP address that you just record in step 1 and enter the IP address and also the MAC address. If you are using the LaunchPad, the MAC address is shown on the sticker on the back of the board. 

    Your PC will be your TFTP server as well as a BootP server to transfer the program image to the MCU (the client). You need to inform the BootP server for the MCU’s IP address and its MAC address. This is how a BootP server works. Unlike a DHCP server, the MAC address and its associated IP address must be manually entered and known ahead of time because BootP is static in nature. This is why we enter them in the configuration tab. However, we don’t know what IP address to enter. We cannot enter any arbitrary address that might interfere with other IP address in the network.

    This is the reason we must first run a different Ethernet example such as enet_lwip. The enet_lwip will send the DHCP request. After the IP address is acquired we will just record the IP address value for reuse in boot_emac_flash. The IP address acquired by running enet_lwip shows 10.219.14.138 in my image. Note your address will be different from mine. The reason we can use this address is that the DHCP IP address is leased for some hours. The address we acquired by running the enet_lwip will be good for a few hours.

    Step 4. Go to the Program tab. Provide the path to the application image which is the boot_demo_emac_flash.bin. This TvaWare example was already llinked to 0x4000. DO NOT change it. You can change to wherever you like in the future. But until you get the example working, do NOT change anything. 

     Step 5. if the boot_emac_flash in step 2 is still halted in CCS, you can run it now. 

     Step 6. After the boot_emac_flash is run, you can hit the Program button in the above image.

     Step 7. Suppose everything went smoothly and the boot_demo_emac_flash application was programmed and if you want to debug it, you can load the symbol by going to Run->Load->Load Symbols. The symbol is contained in the boot_demo_emac_flash.out. Note it is the .out file. Do load symbols, not to be confused with Load program. 

    I will suggest you use WireShark to view the traffic between the MCU and the TFTP/BOOTP server. Below is what you should see. The MCU will send BOOTP request to the PC and after the handshake the TFTP sever sends the program image (boot_demo_emac_flash.bin) to the MCU via the Ethernet interface.

  • still not working please see this video if any issue please help me to solve this 

  • //*****************************************************************************
    //
    // bl_main.c - The file holds the main control loop of the boot loader.
    //
    // Copyright (c) 2006-2020 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    // 
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    // 
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    // 
    // This is part of revision 2.2.0.295 of the Tiva Firmware Development Package.
    //
    //*****************************************************************************
    
    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_gpio.h"
    #include "inc/hw_flash.h"
    #include "inc/hw_i2c.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_nvic.h"
    #include "inc/hw_ssi.h"
    #include "inc/hw_sysctl.h"
    #include "inc/hw_types.h"
    #include "inc/hw_uart.h"
    #include "bl_config.h"
    #include "driverlib/debug.h"
    #include "driverlib/flash.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "boot_loader/bl_commands.h"
    #include "boot_loader/bl_decrypt.h"
    #include "boot_loader/bl_flash.h"
    #include "boot_loader/bl_hooks.h"
    #include "boot_loader/bl_i2c.h"
    #include "boot_loader/bl_packet.h"
    #include "boot_loader/bl_ssi.h"
    #include "boot_loader/bl_uart.h"
    #include "utils/uartstdio.h"
    #include "boot_loader/bl_emac.h"
    
    #include "pinout.h"
    #ifdef CHECK_CRC
    #include "boot_loader/bl_crc32.h"
    #endif
    
    //*****************************************************************************
    //
    // Make sure that the application start address falls on a flash page boundary
    //
    //*****************************************************************************
    #if (APP_START_ADDRESS & (FLASH_PAGE_SIZE - 1))
    #error ERROR: APP_START_ADDRESS must be a multiple of FLASH_PAGE_SIZE bytes!
    #endif
    
    //*****************************************************************************
    //
    // Make sure that the flash reserved space is a multiple of flash pages.
    //
    //*****************************************************************************
    #if (FLASH_RSVD_SPACE & (FLASH_PAGE_SIZE - 1))
    #error ERROR: FLASH_RSVD_SPACE must be a multiple of FLASH_PAGE_SIZE bytes!
    #endif
    
    //*****************************************************************************
    //
    //! \addtogroup bl_main_api
    //! @{
    //
    //*****************************************************************************
    #if defined(I2C_ENABLE_UPDATE) || defined(SSI_ENABLE_UPDATE) || \
        defined(UART_ENABLE_UPDATE) || defined(DOXYGEN)
    
    //*****************************************************************************
    //
    // A prototype for the function (in the startup code) for calling the
    // application.
    //
    //*****************************************************************************
    extern void CallApplication(uint32_t ui32Base);
    
    //*****************************************************************************
    //
    // A prototype for the function (in the startup code) for a predictable length
    // delay.
    //
    //*****************************************************************************
    extern void Delay(uint32_t ui32Count);
    
    //*****************************************************************************
    //
    // Holds the current status of the last command that was issued to the boot
    // loader.
    //
    //*****************************************************************************
    uint8_t g_ui8Status;
    
    //*****************************************************************************
    //
    // This holds the current remaining size in bytes to be downloaded.
    //
    //*****************************************************************************
    uint32_t g_ui32TransferSize;
    
    //*****************************************************************************
    //
    // This holds the total size of the firmware image being downloaded (if the
    // protocol in use provides this).
    //
    //*****************************************************************************
    #if (defined BL_PROGRESS_FN_HOOK) || (defined CHECK_CRC)
    uint32_t g_ui32ImageSize;
    #endif
    
    //*****************************************************************************
    //
    // This holds the current address that is being written to during a download
    // command.
    //
    //*****************************************************************************
    uint32_t g_ui32TransferAddress;
    #ifdef CHECK_CRC
    uint32_t g_ui32ImageAddress;
    #endif
    
    //*****************************************************************************
    //
    // This is the data buffer used during transfers to the boot loader.
    //
    //*****************************************************************************
    uint32_t g_pui32DataBuffer[BUFFER_SIZE];
    
    //*****************************************************************************
    //
    // This is an specially aligned buffer pointer to g_pui32DataBuffer to make
    // copying to the buffer simpler.  It must be offset to end on an address that
    // ends with 3.
    //
    //*****************************************************************************
    uint8_t *g_pui8DataBuffer;
    
    //*****************************************************************************
    //
    // Converts a word from big endian to little endian.  This macro uses compiler-
    // specific constructs to perform an inline insertion of the "rev" instruction,
    // which performs the byte swap directly.
    //
    //*****************************************************************************
    #if defined(ewarm)
    #include <intrinsics.h>
    #define SwapWord(x)             __REV(x)
    #endif
    #if defined(codered) || defined(gcc) || defined(sourcerygxx)
    #define SwapWord(x) __extension__                                             \
            ({                                                                    \
                 register uint32_t __ret, __inp = x;                              \
                 __asm__("rev %0, %1" : "=r" (__ret) : "r" (__inp));              \
                 __ret;                                                           \
            })
    #endif
    #if defined(rvmdk) || defined(__ARMCC_VERSION)
    #define SwapWord(x)             __rev(x)
    #endif
    #if defined(ccs)
    uint32_t
    SwapWord(uint32_t x)
    {
        __asm("    rev     r0, r0\n"
              "    bx      lr\n"); // need this to make sure r0 is returned
        return(x + 1); // return makes compiler happy - ignored
    }
    #endif
    
    //*****************************************************************************
    //
    //! Configures the microcontroller.
    //!
    //! This function configures the peripherals and GPIOs of the microcontroller,
    //! preparing it for use by the boot loader.  The interface that has been
    //! selected as the update port will be configured, and auto-baud will be
    //! performed if required.
    //!
    //! \return None.
    //
    //*****************************************************************************
    void
    ConfigureDevice(void)
    {
    #ifdef UART_ENABLE_UPDATE
        uint32_t ui32ProcRatio;
    #endif
    
    #ifdef CRYSTAL_FREQ
        //
        // Since the crystal frequency was specified, enable the main oscillator
        // and clock the processor from it.
        //
    #if defined(TARGET_IS_TM4C129_RA0) ||                                         \
        defined(TARGET_IS_TM4C129_RA1) ||                                         \
        defined(TARGET_IS_TM4C129_RA2)
        //
        // Since the crystal frequency was specified, enable the main oscillator
        // and clock the processor from it. Check for whether the Oscillator range
        // has to be set and wait states need to be updated
        //
        if(CRYSTAL_FREQ >= 10000000)
        {
            HWREG(SYSCTL_MOSCCTL) |= (SYSCTL_MOSCCTL_OSCRNG);
            HWREG(SYSCTL_MOSCCTL) &= ~(SYSCTL_MOSCCTL_PWRDN |
                                       SYSCTL_MOSCCTL_NOXTAL);
        }
        else
        {
            HWREG(SYSCTL_MOSCCTL) &= ~(SYSCTL_MOSCCTL_PWRDN |
                                       SYSCTL_MOSCCTL_NOXTAL);
        }
    
        //
        // Wait for the Oscillator to Stabilize
        //
        Delay(524288);
    
        if(CRYSTAL_FREQ > 16000000)
        {
            HWREG(SYSCTL_MEMTIM0)  = (SYSCTL_MEMTIM0_FBCHT_1_5 |
                                      (1 << SYSCTL_MEMTIM0_FWS_S) |
                                      SYSCTL_MEMTIM0_EBCHT_1_5 |
                                      (1 << SYSCTL_MEMTIM0_EWS_S) |
                                      SYSCTL_MEMTIM0_MB1);
            HWREG(SYSCTL_RSCLKCFG) = (SYSCTL_RSCLKCFG_MEMTIMU |
                                      SYSCTL_RSCLKCFG_OSCSRC_MOSC);
        }
        else
        {
            HWREG(SYSCTL_RSCLKCFG) = (SYSCTL_RSCLKCFG_OSCSRC_MOSC);
        }
    #else
        HWREG(SYSCTL_RCC) &= ~(SYSCTL_RCC_MOSCDIS);
        Delay(524288);
        HWREG(SYSCTL_RCC) = ((HWREG(SYSCTL_RCC) & ~(SYSCTL_RCC_OSCSRC_M)) |
                             SYSCTL_RCC_OSCSRC_MAIN);
    #endif
    #endif
    
    #ifdef I2C_ENABLE_UPDATE
        //
        // Enable the clocks to the I2C and GPIO modules.
        //
        HWREG(SYSCTL_RCGCGPIO) |= (I2C_SCLPIN_CLOCK_ENABLE |
                                   I2C_SDAPIN_CLOCK_ENABLE);
        HWREG(SYSCTL_RCGCI2C) |= I2C_CLOCK_ENABLE;
    
        //
        // Configure the GPIO pins for hardware control, open drain with pull-up,
        // and enable them.
        //
        HWREG(I2C_SCLPIN_BASE + GPIO_O_AFSEL) |= I2C_CLK;
        HWREG(I2C_SCLPIN_BASE + GPIO_O_PCTL) |= I2C_CLK_PCTL;
        HWREG(I2C_SCLPIN_BASE + GPIO_O_DEN) |= I2C_CLK;
        HWREG(I2C_SCLPIN_BASE + GPIO_O_ODR) &= ~(I2C_CLK);
        HWREG(I2C_SCLPIN_BASE + GPIO_O_PUR) |= I2C_CLK;
    
        HWREG(I2C_SDAPIN_BASE + GPIO_O_AFSEL) |= I2C_DATA;
        HWREG(I2C_SDAPIN_BASE + GPIO_O_PCTL) |= I2C_DATA_PCTL;
        HWREG(I2C_SDAPIN_BASE + GPIO_O_DEN) |= I2C_DATA;
        HWREG(I2C_SDAPIN_BASE + GPIO_O_ODR) |= I2C_DATA;
        HWREG(I2C_SDAPIN_BASE + GPIO_O_PUR) |= I2C_DATA;
    
        //
        // Enable the I2C Slave Mode.
        //
        HWREG(I2Cx_BASE + I2C_O_MCR) = I2C_MCR_MFE | I2C_MCR_SFE;
    
        //
        // Setup the I2C Slave Address.
        //
        HWREG(I2Cx_BASE + I2C_O_SOAR) = I2C_SLAVE_ADDR;
    
        //
        // Enable the I2C Slave Device on the I2C bus.
        //
        HWREG(I2Cx_BASE + I2C_O_SCSR) = I2C_SCSR_DA;
    #endif
    
    #ifdef SSI_ENABLE_UPDATE
        //
        // Enable the clocks to the SSI and GPIO modules.
        //
        HWREG(SYSCTL_RCGCGPIO) |= (SSI_CLKPIN_CLOCK_ENABLE |
                                   SSI_FSSPIN_CLOCK_ENABLE |
                                   SSI_MISOPIN_CLOCK_ENABLE |
                                   SSI_MOSIPIN_CLOCK_ENABLE);
        HWREG(SYSCTL_RCGCSSI) |= SSI_CLOCK_ENABLE;
    
        //
        // Make the pin be peripheral controlled.
        //
        HWREG(SSI_CLKPIN_BASE + GPIO_O_AFSEL) |= SSI_CLK;
        HWREG(SSI_CLKPIN_BASE + GPIO_O_PCTL) |= SSI_CLK_PCTL;
        HWREG(SSI_CLKPIN_BASE + GPIO_O_DEN) |= SSI_CLK;
        HWREG(SSI_CLKPIN_BASE + GPIO_O_ODR) &= ~(SSI_CLK);
    
        HWREG(SSI_FSSPIN_BASE + GPIO_O_AFSEL) |= SSI_CS;
        HWREG(SSI_FSSPIN_BASE + GPIO_O_PCTL) |= SSI_CS_PCTL;
        HWREG(SSI_FSSPIN_BASE + GPIO_O_DEN) |= SSI_CS;
        HWREG(SSI_FSSPIN_BASE + GPIO_O_ODR) &= ~(SSI_CS);
    
        HWREG(SSI_MISOPIN_BASE + GPIO_O_AFSEL) |= SSI_TX;
        HWREG(SSI_MISOPIN_BASE + GPIO_O_PCTL) |= SSI_TX_PCTL;
        HWREG(SSI_MISOPIN_BASE + GPIO_O_DEN) |= SSI_TX;
        HWREG(SSI_MISOPIN_BASE + GPIO_O_ODR) &= ~(SSI_TX);
    
        HWREG(SSI_MOSIPIN_BASE + GPIO_O_AFSEL) |= SSI_RX;
        HWREG(SSI_MOSIPIN_BASE + GPIO_O_PCTL) |= SSI_RX_PCTL;
        HWREG(SSI_MOSIPIN_BASE + GPIO_O_DEN) |= SSI_RX;
        HWREG(SSI_MOSIPIN_BASE + GPIO_O_ODR) &= ~(SSI_RX);
    
        //
        // Set the SSI protocol to Motorola with default clock high and data
        // valid on the rising edge.
        //
        HWREG(SSIx_BASE + SSI_O_CR0) = (SSI_CR0_SPH | SSI_CR0_SPO |
                                        (DATA_BITS_SSI - 1));
    
        //
        // Enable the SSI interface in slave mode.
        //
        HWREG(SSIx_BASE + SSI_O_CR1) = SSI_CR1_MS | SSI_CR1_SSE;
    #endif
    
    #ifdef UART_ENABLE_UPDATE
        //
        // Enable the the clocks to the UART and GPIO modules.
        //
        HWREG(SYSCTL_RCGCGPIO) |= (UART_RXPIN_CLOCK_ENABLE |
                                   UART_TXPIN_CLOCK_ENABLE);
        HWREG(SYSCTL_RCGCUART) |= UART_CLOCK_ENABLE;
    
        //
        // Keep attempting to sync until we are successful.
        //
    #ifdef UART_AUTOBAUD
        while(UARTAutoBaud(&ui32ProcRatio) < 0)
        {
        }
    #else
        ui32ProcRatio = UART_BAUD_RATIO(UART_FIXED_BAUDRATE);
    #endif
    
        //
        // Make the pin be peripheral controlled.
        //
        HWREG(UART_RXPIN_BASE + GPIO_O_AFSEL) |= UART_RX;
        HWREG(UART_RXPIN_BASE + GPIO_O_PCTL) |= UART_RX_PCTL;
        HWREG(UART_RXPIN_BASE + GPIO_O_ODR) &= ~(UART_RX);
        HWREG(UART_RXPIN_BASE + GPIO_O_DEN) |= UART_RX;
    
        HWREG(UART_TXPIN_BASE + GPIO_O_AFSEL) |= UART_TX;
        HWREG(UART_TXPIN_BASE + GPIO_O_PCTL) |= UART_TX_PCTL;
        HWREG(UART_TXPIN_BASE + GPIO_O_ODR) &= ~(UART_TX);
        HWREG(UART_TXPIN_BASE + GPIO_O_DEN) |= UART_TX;
    
        //
        // Set the baud rate.
        //
        HWREG(UARTx_BASE + UART_O_IBRD) = ui32ProcRatio >> 6;
        HWREG(UARTx_BASE + UART_O_FBRD) = ui32ProcRatio & UART_FBRD_DIVFRAC_M;
    
        //
        // Set data length, parity, and number of stop bits to 8-N-1.
        //
        HWREG(UARTx_BASE + UART_O_LCRH) = UART_LCRH_WLEN_8 | UART_LCRH_FEN;
    
        //
        // Enable RX, TX, and the UART.
        //
        HWREG(UARTx_BASE + UART_O_CTL) = (UART_CTL_UARTEN | UART_CTL_TXE |
                                          UART_CTL_RXE);
    
    #ifdef UART_AUTOBAUD
        //
        // Need to ack in the UART case to hold it up while we get things set up.
        //
        AckPacket();
    #endif
    #endif
    }
    
    //*****************************************************************************
    //
    //! This function performs the update on the selected port.
    //!
    //! This function is called directly by the boot loader or it is called as a
    //! result of an update request from the application.
    //!
    //! \return Never returns.
    //
    //*****************************************************************************
    void
    Updater(void)
    {
        uint32_t ui32Size, ui32Temp, ui32FlashSize;
    #ifdef CHECK_CRC
        uint32_t ui32Retcode;
    #endif
    
        //
        // This ensures proper alignment of the global buffer so that the one byte
        // size parameter used by the packetized format is easily skipped for data
        // transfers.
        //
        g_pui8DataBuffer = ((uint8_t *)g_pui32DataBuffer) + 3;
    
        //
        // Insure that the COMMAND_SEND_DATA cannot be sent to erase the boot
        // loader before the application is erased.
        //
        g_ui32TransferAddress = 0xffffffff;
    
        //
        // Read any data from the serial port in use.
        //
        while(1)
        {
            //
            // Receive a packet from the port in use.
            //
            ui32Size = sizeof(g_pui32DataBuffer) - 3;
            if(ReceivePacket(g_pui8DataBuffer, &ui32Size) != 0)
            {
                continue;
            }
    
            //
            // The first byte of the data buffer has the command and determines
            // the format of the rest of the bytes.
            //
            switch(g_pui8DataBuffer[0])
            {
                //
                // This was a simple ping command.
                //
                case COMMAND_PING:
                {
                    //
                    // This command always sets the status to COMMAND_RET_SUCCESS.
                    //
                    g_ui8Status = COMMAND_RET_SUCCESS;
    
                    //
                    // Just acknowledge that the command was received.
                    //
                    AckPacket();
    
                    //
                    // Go back and wait for a new command.
                    //
                    break;
                }
    
                //
                // This command indicates the start of a download sequence.
                //
                case COMMAND_DOWNLOAD:
                {
                    //
                    // Until determined otherwise, the command status is success.
                    //
                    g_ui8Status = COMMAND_RET_SUCCESS;
    
                    //
                    // A simple do/while(0) control loop to make error exits
                    // easier.
                    //
                    do
                    {
                        //
                        // See if a full packet was received.
                        //
                        if(ui32Size != 9)
                        {
                            //
                            // Indicate that an invalid command was received.
                            //
                            g_ui8Status = COMMAND_RET_INVALID_CMD;
    
                            //
                            // This packet has been handled.
                            //
                            break;
                        }
    
                        //
                        // Get the address and size from the command.
                        //
                        g_ui32TransferAddress = SwapWord(g_pui32DataBuffer[1]);
                        g_ui32TransferSize = SwapWord(g_pui32DataBuffer[2]);
    
                        //
                        // Depending upon the build options set, keep a copy of
                        // the original size and start address because we will need
                        // these later.
                        //
    #if (defined BL_PROGRESS_FN_HOOK) || (defined CHECK_CRC)
                        g_ui32ImageSize = g_ui32TransferSize;
    #endif
    #ifdef CHECK_CRC
                        g_ui32ImageAddress = g_ui32TransferAddress;
    #endif
    
                        //
                        // Check for a valid starting address and image size.
                        //
                        if(!BL_FLASH_AD_CHECK_FN_HOOK(g_ui32TransferAddress,
                                                      g_ui32TransferSize))
                        {
                            //
                            // Set the code to an error to indicate that the last
                            // command failed.  This informs the updater program
                            // that the download command failed.
                            //
                            g_ui8Status = COMMAND_RET_INVALID_ADR;
    
                            //
                            // This packet has been handled.
                            //
                            break;
                        }
    
    
                        //
                        // Only erase the space that we need if we are not
                        // protecting the code, otherwise erase the entire flash.
                        //
    #ifdef FLASH_CODE_PROTECTION
                        ui32FlashSize = BL_FLASH_SIZE_FN_HOOK();
    #ifdef FLASH_RSVD_SPACE
                        if((ui32FlashSize - FLASH_RSVD_SPACE) !=
                           g_ui32TransferAddress)
                        {
                            ui32FlashSize -= FLASH_RSVD_SPACE;
                        }
    #endif
    #else
                        ui32FlashSize = g_ui32TransferAddress + g_ui32TransferSize;
    #endif
    
                        //
                        // Clear the flash access interrupt.
                        //
                        BL_FLASH_CL_ERR_FN_HOOK();
    
                        //
                        // Leave the boot loader present until we start getting an
                        // image.
                        //
                        for(ui32Temp = g_ui32TransferAddress;
                            ui32Temp < ui32FlashSize; ui32Temp += FLASH_PAGE_SIZE)
                        {
                            //
                            // Erase this block.
                            //
                            BL_FLASH_ERASE_FN_HOOK(ui32Temp);
                        }
    
                        //
                        // Return an error if an access violation occurred.
                        //
                        if(BL_FLASH_ERROR_FN_HOOK())
                        {
                            g_ui8Status = COMMAND_RET_FLASH_FAIL;
                        }
                    }
                    while(0);
    
                    //
                    // See if the command was successful.
                    //
                    if(g_ui8Status != COMMAND_RET_SUCCESS)
                    {
                        //
                        // Setting g_ui32TransferSize to zero makes
                        // COMMAND_SEND_DATA fail to accept any data.
                        //
                        g_ui32TransferSize = 0;
                    }
    
                    //
                    // Acknowledge that this command was received correctly.  This
                    // does not indicate success, just that the command was
                    // received.
                    //
                    AckPacket();
    
                    //
                    // If we have a start notification hook function, call it
                    // now if everything is OK.
                    //
    #ifdef BL_START_FN_HOOK
                    if(g_ui32TransferSize)
                    {
                        BL_START_FN_HOOK();
                    }
    #endif
    
                    //
                    // Go back and wait for a new command.
                    //
                    break;
                }
    
                //
                // This command indicates that control should be transferred to
                // the specified address.
                //
                case COMMAND_RUN:
                {
                    //
                    // Acknowledge that this command was received correctly.  This
                    // does not indicate success, just that the command was
                    // received.
                    //
                    AckPacket();
    
                    //
                    // See if a full packet was received.
                    //
                    if(ui32Size != 5)
                    {
                        //
                        // Indicate that an invalid command was received.
                        //
                        g_ui8Status = COMMAND_RET_INVALID_CMD;
    
                        //
                        // This packet has been handled.
                        //
                        break;
                    }
    
                    //
                    // Get the address to which control should be transferred.
                    //
                    g_ui32TransferAddress = SwapWord(g_pui32DataBuffer[1]);
    
                    //
                    // This determines the size of the flash available on the
                    // device in use.
                    //
                    ui32FlashSize = BL_FLASH_SIZE_FN_HOOK();
    
                    //
                    // Test if the transfer address is valid for this device.
                    //
                    if(g_ui32TransferAddress >= ui32FlashSize)
                    {
                        //
                        // Indicate that an invalid address was specified.
                        //
                        g_ui8Status = COMMAND_RET_INVALID_ADR;
    
                        //
                        // This packet has been handled.
                        //
                        break;
                    }
    
                    //
                    // Make sure that the ACK packet has been sent.
                    //
                    FlushData();
    
                    //
                    // Reset and disable the peripherals used by the boot loader.
                    //
    #ifdef I2C_ENABLE_UPDATE
                    HWREG(SYSCTL_RCGCI2C) &= ~I2C_CLOCK_ENABLE;
                    HWREG(SYSCTL_SRI2C) = I2C_CLOCK_ENABLE;
                    HWREG(SYSCTL_SRI2C) = 0;
    #endif
    #ifdef UART_ENABLE_UPDATE
                    HWREG(SYSCTL_RCGCUART) &= ~UART_CLOCK_ENABLE;
                    HWREG(SYSCTL_SRUART) = UART_CLOCK_ENABLE;
                    HWREG(SYSCTL_SRUART) = 0;
    #endif
    #ifdef SSI_ENABLE_UPDATE
                    HWREG(SYSCTL_RCGCSSI) &= ~SSI_CLOCK_ENABLE;
                    HWREG(SYSCTL_SRSSI) = SSI_CLOCK_ENABLE;
                    HWREG(SYSCTL_SRSSI) = 0;
    #endif
    
                    //
                    // Branch to the specified address.  This should never return.
                    // If it does, very bad things will likely happen since it is
                    // likely that the copy of the boot loader in SRAM will have
                    // been overwritten.
                    //
                    ((void (*)(void))g_ui32TransferAddress)();
    
                    //
                    // In case this ever does return and the boot loader is still
                    // intact, simply reset the device.
                    //
                    HWREG(NVIC_APINT) = (NVIC_APINT_VECTKEY |
                                         NVIC_APINT_SYSRESETREQ);
    
                    //
                    // The microcontroller should have reset, so this should
                    // never be reached.  Just in case, loop forever.
                    //
                    while(1)
                    {
                    }
                }
    
                //
                // This command just returns the status of the last command that
                // was sent.
                //
                case COMMAND_GET_STATUS:
                {
                    //
                    // Acknowledge that this command was received correctly.  This
                    // does not indicate success, just that the command was
                    // received.
                    //
                    AckPacket();
    
                    //
                    // Return the status to the updater.
                    //
                    SendPacket(&g_ui8Status, 1);
    
                    //
                    // Go back and wait for a new command.
                    //
                    break;
                }
    
                //
                // This command is sent to transfer data to the device following
                // a download command.
                //
                case COMMAND_SEND_DATA:
                {
                    //
                    // Until determined otherwise, the command status is success.
                    //
                    g_ui8Status = COMMAND_RET_SUCCESS;
    
                    //
                    // If this is overwriting the boot loader then the application
                    // has already been erased so now erase the boot loader.
                    //
                    if(g_ui32TransferAddress == 0)
                    {
                        //
                        // Clear the flash access interrupt.
                        //
                        BL_FLASH_CL_ERR_FN_HOOK();
    
                        //
                        // Erase the boot loader.
                        //
                        for(ui32Temp = 0; ui32Temp < APP_START_ADDRESS;
                            ui32Temp += FLASH_PAGE_SIZE)
                        {
                            //
                            // Erase this block.
                            //
                            BL_FLASH_ERASE_FN_HOOK(ui32Temp);
                        }
    
                        //
                        // Return an error if an access violation occurred.
                        //
                        if(BL_FLASH_ERROR_FN_HOOK())
                        {
                            //
                            // Setting g_ui32TransferSize to zero makes
                            // COMMAND_SEND_DATA fail to accept any more data.
                            //
                            g_ui32TransferSize = 0;
    
                            //
                            // Indicate that the flash erase failed.
                            //
                            g_ui8Status = COMMAND_RET_FLASH_FAIL;
                        }
                    }
    
                    //
                    // Take one byte off for the command.
                    //
                    ui32Size = ui32Size - 1;
    
                    //
                    // Check if there are any more bytes to receive.
                    //
                    if(g_ui32TransferSize >= ui32Size)
                    {
                        //
                        // If we have been provided with a decryption hook function
                        // call it here.
                        //
    #ifdef BL_DECRYPT_FN_HOOK
                        BL_DECRYPT_FN_HOOK(g_pui8DataBuffer + 1, ui32Size);
    #endif
    
                        //
                        // Write this block of data to the flash
                        //
                        BL_FLASH_PROGRAM_FN_HOOK(g_ui32TransferAddress,
                                                 (uint8_t *) &g_pui32DataBuffer[1],
                                                 ((ui32Size + 3) & ~3));
    
                        //
                        // Return an error if an access violation occurred.
                        //
                        if(BL_FLASH_ERROR_FN_HOOK())
                        {
                            //
                            // Indicate that the flash programming failed.
                            //
                            g_ui8Status = COMMAND_RET_FLASH_FAIL;
                        }
                        else
                        {
                            //
                            // Now update the address to program.
                            //
                            g_ui32TransferSize -= ui32Size;
                            g_ui32TransferAddress += ui32Size;
    
                            //
                            // If a progress hook function has been provided, call
                            // it here.
                            //
    #ifdef BL_PROGRESS_FN_HOOK
                            BL_PROGRESS_FN_HOOK(g_ui32ImageSize -
                                                g_ui32TransferSize,
                                                g_ui32ImageSize);
    #endif
    
    #ifdef CHECK_CRC
                            //
                            // If we've reached the end, check the CRC in the
                            // image to determine whether or not we report an error
                            // back to the host.
                            //
                            if(g_ui32TransferSize == 0)
                            {
                                InitCRC32Table();
                                ui32Retcode = CheckImageCRC32(
                                        (uint32_t *)g_ui32ImageAddress);
    
                                //
                                // Was the CRC good?  We consider the CRC good if
                                // the header is found and the embedded CRC matches
                                // the calculated value or, if ENFORCE_CRC is not
                                // defined, if the header exists but is unpopulated.
                                //
    #ifdef ENFORCE_CRC
                                if(ui32Retcode == CHECK_CRC_OK)
    #else
                                if((ui32Retcode == CHECK_CRC_OK) ||
                                   (ui32Retcode == CHECK_CRC_NO_LENGTH))
    #endif
                                {
                                    //
                                    // The calculated CRC agreed with the embedded
                                    // value.
                                    //
                                    g_ui8Status = COMMAND_RET_SUCCESS;
                                }
                                else
                                {
                                    //
                                    // The calculated CRC didn't match the expected
                                    // value or the image didn't contain an embedded
                                    // CRC.
                                    //
                                    g_ui8Status = COMMAND_RET_CRC_FAIL;
                                }
                            }
    #endif
                        }
                    }
                    else
                    {
                        //
                        // This indicates that too much data is being sent to the
                        // device.
                        //
                        g_ui8Status = COMMAND_RET_INVALID_ADR;
                    }
    
                    //
                    // Acknowledge that this command was received correctly.  This
                    // does not indicate success, just that the command was
                    // received.
                    //
                    AckPacket();
    
                    //
                    // If we have an end notification hook function, and we've
                    // reached the end, call it now.
                    //
    #ifdef BL_END_FN_HOOK
                    if(g_ui32TransferSize == 0)
                    {
                        BL_END_FN_HOOK();
                    }
    #endif
    
                    //
                    // Go back and wait for a new command.
                    //
                    break;
                }
    
                //
                // This command is used to reset the device.
                //
                case COMMAND_RESET:
                {
                    //
                    // Send out a one-byte ACK to ensure the byte goes back to the
                    // host before we reset everything.
                    //
                    AckPacket();
    
                    //
                    // Make sure that the ACK packet has been sent.
                    //
                    FlushData();
    
                    //
                    // Perform a software reset request.  This will cause the
                    // microcontroller to reset; no further code will be executed.
                    //
                    HWREG(NVIC_APINT) = (NVIC_APINT_VECTKEY |
                                         NVIC_APINT_SYSRESETREQ);
    
                    //
                    // The microcontroller should have reset, so this should never
                    // be reached.  Just in case, loop forever.
                    //
                    while(1)
                    {
                    }
                }
    
                //
                // Just acknowledge the command and set the error to indicate that
                // a bad command was sent.
                //
                default:
                {
                    //
                    // Acknowledge that this command was received correctly.  This
                    // does not indicate success, just that the command was
                    // received.
                    //
                    AckPacket();
    
                    //
                    // Indicate that a bad comand was sent.
                    //
                    g_ui8Status = COMMAND_RET_UNKNOWN_CMD;
    
                    //
                    // Go back and wait for a new command.
                    //
                    break;
                }
            }
        }
    }
    #endif
    //****************************************************************************
    //
    // The variable g_ui32SysClock contains the system clock frequency in Hz.
    //
    //****************************************************************************
    uint32_t g_ui32SysClock;
    
    
    int main(void)
    {
    
    
        //
        // Enable lazy stacking for interrupt handlers.  This allows floating-point
        // instructions to be used within interrupt handlers, but at the expense of
        // extra stack usage.
        //
        MAP_FPULazyStackingEnable();
    
        //
        // Run from the PLL at 120 MHz.
        // Note: SYSCTL_CFG_VCO_240 is a new setting provided in TivaWare 2.2.x and
        // later to better reflect the actual VCO speed due to SYSCTL#22.
        //
        g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                                 SYSCTL_OSC_MAIN |
                                                 SYSCTL_USE_PLL |
                                                 SYSCTL_CFG_VCO_240), 120000000);
    
    
       //
       // Configure the device pins.
       //
       PinoutSet(true, false);
    
       //
       // Configure debug port for internal use.
       //
       UARTStdioConfig(0, 115200, g_ui32SysClock);
    
       //
       // Clear the terminal and print a banner.
       //
       UARTprintf("\033[2J\033[H");
       UARTprintf("Ethernet Boot-loader\n\n");
    
    
       UpdateBOOTP();
    
    
        return 0;
    }
    
    
    //*****************************************************************************
    //
    // Close the Doxygen group.
    //! @}
    //
    //*****************************************************************************
    
    

    bl_main.c my changes

  • //*****************************************************************************
    //
    // bl_config.h - The configurable parameters of the boot loader.
    //
    // Copyright (c) 2015-2020 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    // 
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    // 
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    // 
    // This is part of revision 2.2.0.295 of the EK-TM4C1294XL Firmware Package.
    //
    //*****************************************************************************
    
    #ifndef __BL_CONFIG_H__
    #define __BL_CONFIG_H__
    
    //*****************************************************************************
    //
    // The following defines are used to configure the operation of the boot
    // loader.  For each define, its interactions with other defines are described.
    // First is the dependencies (in other words, the defines that must also be
    // defined if it is defined), next are the exclusives (in other words, the
    // defines that can not be defined if it is defined), and finally are the
    // requirements (in other words, the defines that must be defined if it is
    // defined).
    //
    // The following defines must be defined in order for the boot loader to
    // operate:
    //
    //     One of CAN_ENABLE_UPDATE, ENET_ENABLE_UPDATE, I2C_ENABLE_UPDATE,
    //            SSI_ENABLE_UPDATE, UART_ENABLE_UPDATE, or USB_ENABLE_UPDATE
    //     APP_START_ADDRESS
    //     VTABLE_START_ADDRESS
    //     FLASH_PAGE_SIZE
    //     STACK_SIZE
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // The frequency of the crystal used to clock the microcontroller.
    //
    // This defines the crystal frequency used by the microcontroller running the
    // boot loader.  If this is unknown at the time of production, then use the
    // UART_AUTOBAUD feature to properly configure the UART.
    //
    // Depends on: None
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    #define CRYSTAL_FREQ            25000000
    
    //*****************************************************************************
    //
    // The starting address of the application.  This must be a multiple of 1024
    // bytes (making it aligned to a page boundary).  A vector table is expected at
    // this location, and the perceived validity of the vector table (stack located
    // in SRAM, reset vector located in flash) is used as an indication of the
    // validity of the application image.
    //
    // The flash image of the boot loader must not be larger than this value.
    //
    // Depends on: None
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    #define APP_START_ADDRESS       0x00004000
    
    //*****************************************************************************
    //
    // The address at which the application locates its exception vector table.
    // This must be a multiple of 1024 bytes (making it aligned to a page
    // boundary).  Typically, an application will start with its vector table and
    // this value should be set to APP_START_ADDRESS.  This option is provided to
    // cater for applications which run from external memory which may not be
    // accessible by the NVIC (the vector table offset register is only 30 bits
    // long).
    //
    // Depends on: None
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    #define VTABLE_START_ADDRESS    0x00004000
    
    //*****************************************************************************
    //
    // The size of a single, erasable page in the flash.  This must be a power
    // of 2.
    //
    // Depends on: None
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    #define FLASH_PAGE_SIZE         0x4000
    
    //*****************************************************************************
    //
    // The amount of space at the end of flash to reserved.  This must be a
    // multiple of 1024 bytes (making it aligned to a page boundary).  This
    // reserved space is not erased when the application is updated, providing
    // non-volatile storage that can be used for parameters.
    //
    // Depends on: None
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define FLASH_RSVD_SPACE        0x00000800
    
    //*****************************************************************************
    //
    // The number of words of stack space to reserve for the boot loader.
    //
    // Depends on: None
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    #define STACK_SIZE              256
    
    //*****************************************************************************
    //
    // The number of words in the data buffer used for receiving packets.  This
    // value must be at least 3.  If using auto-baud on the UART, this must be at
    // least 20.  The maximum usable value is 65 (larger values will result in
    // unused space in the buffer).
    //
    // Depends on: None
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    #define BUFFER_SIZE             20
    
    //*****************************************************************************
    //
    // Enables updates to the boot loader.  Updating the boot loader is an unsafe
    // operation since it is not fully fault tolerant (losing power to the device
    // part way through could result in the boot loader no longer being present in
    // flash).
    //
    // Depends on: None
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define ENABLE_BL_UPDATE
    
    //*****************************************************************************
    //
    // Enables runtime and download CRC32 checking of the main firmware image.
    // If this is defined, the boot loader will scan the main firmware image for
    // an image information header (stored immediately above the vector table and
    // marked by the words 0xFF01FF02 and 0xFF03FF04).  If the header is found and
    // the CRC32 value it contains matches that calculated for the image, the
    // firmware is run.  If the CRC32 does not match or the image information
    // is not found, the boot loader retains control and waits for a new download.
    // To aid debugging, if this option is used without ENFORCE_CRC being set, the
    // image will also be booted if the header is present but the length field is
    // set to 0xFFFFFFFF, typically indicating that the firmware file has not been
    // run through the post-processing tool which inserts the length and CRC values.
    //
    // Note that firmware images intended for use with CRC checking must have been
    // built with an 8 word image header appended to the top of the vector table
    // and the binary must have been processed by a tool such as tools/binpack.exe
    // to ensure that the required length (3rd word) and CRC32 (4th word) fields
    // are populated in the header.
    //
    // Depends on: ENFORCE_CRC
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define CHECK_CRC
    
    //*****************************************************************************
    //
    // This definition may be used alongside CHECK_CRC to remove the debug behavior
    // which will allow an image with an uninitialized header to be run.  With
    // ENFORCE_CRC defined firmware images will only be booted if they contain a
    // valid image information header and if the embedded CRC32 in that header
    // matches the calculated value.
    //
    // Depends on: None
    // Exclusive of: None
    // Requires: CHECK_CRC
    //
    //*****************************************************************************
    //#define ENFORCE_CRC
    
    //*****************************************************************************
    //
    // This definition will cause the the boot loader to erase the entire flash on
    // updates to the boot loader or to erase the entire application area when the
    // application is updated.  This erases any unused sections in the flash before
    // the firmware is updated.
    //
    // Depends on: None
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define FLASH_CODE_PROTECTION
    
    //*****************************************************************************
    //
    // Enables the call to decrypt the downloaded data before writing it into
    // flash.  The decryption routine is empty in the reference boot loader source,
    // which simply provides a placeholder for adding an actual decryption
    // algorithm.  Although this option is retained for backwards compatibility, it
    // is recommended that a decryption function be specified using the newer hook
    // function mechanism and BL_DECRYPT_FN_HOOK instead.
    //
    // Depends on: None
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define ENABLE_DECRYPTION
    
    //*****************************************************************************
    //
    // Enables support for the MOSCFAIL handler in the NMI interrupt.
    //
    // Depends on: None
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define ENABLE_MOSCFAIL_HANDLER
    
    //*****************************************************************************
    //
    // Enables the pin-based forced update check.  When enabled, the boot loader
    // will go into update mode instead of calling the application if a pin is read
    // at a particular polarity, forcing an update operation.  In either case, the
    // application is still able to return control to the boot loader in order to
    // start an update.  For applications which need to perform more complex
    // checking than is possible using a single GPIO, a hook function may be
    // provided using BL_CHECK_UPDATE_FN_HOOK instead.
    //
    // Depends on: None
    // Exclusive of: None
    // Requires: FORCED_UPDATE_PERIPH, FORCED_UPDATE_PORT, FORCED_UPDATE_PIN,
    //           FORCED_UPDATE_POLARITY
    //
    //*****************************************************************************
    //#define ENABLE_UPDATE_CHECK
    
    //*****************************************************************************
    //
    // The GPIO module to enable in order to check for a forced update.  This will
    // be one of the SYSCTL_RCGC2_GPIOx values, where "x" is replaced with the port
    // name (such as B).  The value of "x" should match the value of "x" for
    // FORCED_UPDATE_PORT.
    //
    // Depends on: ENABLE_UPDATE_CHECK
    // Exclusive of: None
    // Requries: None
    //
    //*****************************************************************************
    //#define FORCED_UPDATE_PERIPH    SYSCTL_RCGC2_GPIOB
    
    //*****************************************************************************
    //
    // The GPIO port to check for a forced update.  This will be one of the
    // GPIO_PORTx_BASE values, where "x" is replaced with the port name (such as
    // B).  The value of "x" should match the value of "x" for
    // FORCED_UPDATE_PERIPH.
    //
    // Depends on: ENABLE_UPDATE_CHECK
    // Exclusive of: None
    // Requries: None
    //
    //*****************************************************************************
    //#define FORCED_UPDATE_PORT      GPIO_PORTB_BASE
    
    //*****************************************************************************
    //
    // The pin to check for a forced update.  This is a value between 0 and 7.
    //
    // Depends on: ENABLE_UPDATE_CHECK
    // Exclusive of: None
    // Requries: None
    //
    //*****************************************************************************
    //#define FORCED_UPDATE_PIN       4
    
    //*****************************************************************************
    //
    // The polarity of the GPIO pin that results in a forced update.  This value
    // should be 0 if the pin should be low and 1 if the pin should be high.
    //
    // Depends on: ENABLE_UPDATE_CHECK
    // Exclusive of: None
    // Requries: None
    //
    //*****************************************************************************
    //#define FORCED_UPDATE_POLARITY  0
    
    //*****************************************************************************
    //
    // This enables a weak pull-up or pull-down for the GPIO pin used in a forced
    // update.  Only one of FORCED_UPDATE_WPU or FORCED_UPDATE_WPD should be
    // defined, or neither if a weak pull-up or pull-down is not required.
    //
    // Depends on: ENABLE_UPDATE_CHECK
    // Exclusive of: None
    // Requries: None
    //
    //*****************************************************************************
    //#define FORCED_UPDATE_WPU
    //#define FORCED_UPDATE_WPD
    
    //*****************************************************************************
    //
    // This enables the use of the GPIO_LOCK mechanism for configuration of
    // protected GPIO pins (for example JTAG pins).  If this value is not defined,
    // the locking mechanism will not be used.  The only legal values for this
    // feature are GPIO_LOCK_KEY for Fury devices and GPIO_LOCK_KEY_DD for all
    // other devices except Sandstorm devices, which do not support this feature.
    //
    // Depends on: ENABLE_UPDATE_CHECK
    // Exclusive of: None
    // Requries: None
    //
    //*****************************************************************************
    //#define FORCED_UPDATE_KEY       GPIO_LOCK_KEY
    //#define FORCED_UPDATE_KEY       GPIO_LOCK_KEY_DD
    
    //*****************************************************************************
    //
    // Selects the UART as the port for communicating with the boot loader.
    //
    // Depends on: None
    // Exclusive of: CAN_ENABLE_UPDATE, ENET_ENABLE_UPDATE, I2C_ENABLE_UPDATE,
    //               SSI_ENABLE_UPDATE, USB_ENABLE_UPDATE
    // Requires: UART_AUTOBAUD or UART_FIXED_BAUDRATE, UART_CLOCK_ENABLE, 
    //           UARTx_BASE, UART_RXPIN_CLOCK_ENABLE, UART_RXPIN_BASE, 
    //           UART_RXPIN_PCTL, UART_RXPIN_POS, UART_TXPIN_CLOCK_ENABLE,
    //           UART_TXPIN_BASE, UART_TXPIN_PCTL and UART_TXPIN_POS
    //
    //*****************************************************************************
    //#define UART_ENABLE_UPDATE
    
    //*****************************************************************************
    //
    // Enables automatic baud rate detection.  This can be used if the crystal
    // frequency is unknown, or if operation at different baud rates is desired.
    //
    // Depends on: UART_ENABLE_UPDATE
    // Exclusive of: UART_FIXED_BAUDRATE
    // Requires: None
    //
    //*****************************************************************************
    //#define UART_AUTOBAUD
    
    //*****************************************************************************
    //
    // Selects the baud rate to be used for the UART.
    //
    // Depends on: UART_ENABLE_UPDATE, CRYSTAL_FREQ
    // Exclusive of: UART_AUTOBAUD
    // Requires: None
    //
    //*****************************************************************************
    //#define UART_FIXED_BAUDRATE     115200
    
    //*****************************************************************************
    //
    // Selects the clock enable for the UART peripheral module
    //
    // Depends on: UART_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: UARTx_BASE
    //
    //*****************************************************************************
    //#define UART_CLOCK_ENABLE     SYSCTL_RCGCUART_R0
    
    //*****************************************************************************
    //
    // Selects the base address of the UART peripheral module
    //
    // Depends on: UART_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: UART_CLOCK_ENABLE
    //
    //*****************************************************************************
    //#define UARTx_BASE     UART0_BASE
    
    //*****************************************************************************
    //
    // Selects the clock enable for the GPIO corresponding to UART RX pin
    //
    // Depends on: UART_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: UART_RXPIN_BASE, UART_RXPIN_PCTL and UART_RXPIN_POS
    //
    //*****************************************************************************
    //#define UART_RXPIN_CLOCK_ENABLE     SYSCTL_RCGCGPIO_R0
    
    //*****************************************************************************
    //
    // Selects the base address for the GPIO corresponding to UART RX pin
    //
    // Depends on: UART_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: UART_RXPIN_CLOCK_ENABLE, UART_RXPIN_PCTL and UART_RXPIN_POS
    //
    //*****************************************************************************
    //#define UART_RXPIN_BASE     GPIO_PORTA_BASE
    
    //*****************************************************************************
    //
    // Selects the port control value for the GPIO corresponding to UART RX pin
    //
    // Depends on: UART_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: UART_RXPIN_CLOCK_ENABLE, UART_RXPIN_BASE and UART_RXPIN_POS
    //
    //*****************************************************************************
    //#define UART_RXPIN_PCTL     0x1
    
    //*****************************************************************************
    //
    // Selects the pin number for the GPIO corresponding to UART RX pin
    //
    // Depends on: UART_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: UART_RXPIN_CLOCK_ENABLE, UART_RXPIN_BASE and UART_RXPIN_PCTL
    //
    //*****************************************************************************
    //#define UART_RXPIN_POS     0
    
    //*****************************************************************************
    //
    // Selects the clock enable for the GPIO corresponding to UART TX pin
    //
    // Depends on: UART_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: UART_TXPIN_BASE, UART_TXPIN_PCTL and UART_TXPIN_POS
    //
    //*****************************************************************************
    //#define UART_TXPIN_CLOCK_ENABLE     SYSCTL_RCGCGPIO_R0
    
    //*****************************************************************************
    //
    // Selects the base address for the GPIO corresponding to UART TX pin
    //
    // Depends on: UART_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: UART_TXPIN_CLOCK_ENABLE, UART_TXPIN_PCTL and UART_TXPIN_POS
    //
    //*****************************************************************************
    //#define UART_TXPIN_BASE     GPIO_PORTA_BASE
    
    //*****************************************************************************
    //
    // Selects the port control value for the GPIO corresponding to UART TX pin
    //
    // Depends on: UART_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: UART_TXPIN_CLOCK_ENABLE, UART_TXPIN_BASE and UART_TXPIN_POS
    //
    //*****************************************************************************
    //#define UART_TXPIN_PCTL     0x1
    
    //*****************************************************************************
    //
    // Selects the pin number for the GPIO corresponding to UART TX pin
    //
    // Depends on: UART_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: UART_TXPIN_CLOCK_ENABLE, UART_TXPIN_BASE and UART_TXPIN_PCTL
    //
    //*****************************************************************************
    //#define UART_TXPIN_POS     1
    
    //*****************************************************************************
    //
    // Selects the SSI port as the port for communicating with the boot loader.
    //
    // Depends on: None
    // Exclusive of: CAN_ENABLE_UPDATE, ENET_ENABLE_UPDATE, I2C_ENABLE_UPDATE,
    //               UART_ENABLE_UPDATE, USB_ENABLE_UPDATE
    // Requires: SSI_CLOCK_ENABLE, SSIx_BASE, SSI_CLKPIN_CLOCK_ENABLE, 
    //           SSI_CLKPIN_BASE, SSI_CLKPIN_PCTL, SSI_CLKPIN_POS, 
    //           SSI_FSSPIN_CLOCK_ENABLE, SSI_FSSPIN_BASE, SSI_FSSPIN_PCTL,
    //           SSI_FSSPIN_POS, SSI_MISOPIN_CLOCK_ENABLE, SSI_MISOPIN_BASE,
    //           SSI_MISOPIN_PCTL, SSI_MISOPIN_POS, SSI_MOSIPIN_CLOCK_ENABLE,
    //           SSI_MOSIPIN_BASE, SSI_MOSIPIN_PCTL and SSI_MOSIPIN_POS
    //
    //*****************************************************************************
    //#define SSI_ENABLE_UPDATE
    
    //*****************************************************************************
    //
    // Selects the clock enable for the SSI peripheral module
    //
    // Depends on: SSI_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: SSIx_BASE
    //
    //*****************************************************************************
    //#define SSI_CLOCK_ENABLE          SYSCTL_RCGCSSI_R0
    
    //*****************************************************************************
    //
    // Selects the base address of the SSI peripheral module
    //
    // Depends on: SSI_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: SSI_CLOCK_ENABLE
    //
    //*****************************************************************************
    //#define SSIx_BASE          SSI0_BASE
    
    //*****************************************************************************
    //
    // Selects the clock enable for the GPIO corresponding to SSI CLK pin
    //
    // Depends on: SSI_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: SSI_CLKPIN_BASE, SSI_CLKPIN_PCTL and SSI_CLKPIN_POS
    //
    //*****************************************************************************
    //#define SSI_CLKPIN_CLOCK_ENABLE          SYSCTL_RCGCGPIO_R0
    
    //*****************************************************************************
    //
    // Selects the base address for the GPIO corresponding to SSI CLK pin
    //
    // Depends on: SSI_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: SSI_CLKPIN_CLOCK_ENABLE, SSI_CLKPIN_PCTL and SSI_CLKPIN_POS
    //
    //*****************************************************************************
    //#define SSI_CLKPIN_BASE          GPIO_PORTA_BASE
    
    //*****************************************************************************
    //
    // Selects the port control value for the GPIO corresponding to SSI CLK pin
    //
    // Depends on: SSI_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: SSI_CLKPIN_CLOCK_ENABLE, SSI_CLKPIN_BASE and SSI_CLKPIN_POS
    //
    //*****************************************************************************
    //#define SSI_CLKPIN_PCTL          0x2
    
    //*****************************************************************************
    //
    // Selects the pin number for the GPIO corresponding to SSI CLK pin
    //
    // Depends on: SSI_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: SSI_CLKPIN_CLOCK_ENABLE, SSI_CLKPIN_BASE and SSI_CLKPIN_PCTL
    //
    //*****************************************************************************
    //#define SSI_CLKPIN_POS          2
    
    //*****************************************************************************
    //
    // Selects the clock enable for the GPIO corresponding to SSI FSS pin
    //
    // Depends on: SSI_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: SSI_FSSPIN_BASE, SSI_FSSPIN_PCTL and SSI_FSSPIN_POS
    //
    //*****************************************************************************
    //#define SSI_FSSPIN_CLOCK_ENABLE          SYSCTL_RCGCGPIO_R0
    
    //*****************************************************************************
    //
    // Selects the base address for the GPIO corresponding to SSI FSS pin
    //
    // Depends on: SSI_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: SSI_FSSPIN_CLOCK_ENABLE, SSI_FSSPIN_PCTL and SSI_FSSPIN_POS
    //
    //*****************************************************************************
    //#define SSI_FSSPIN_BASE          GPIO_PORTA_BASE
    
    //*****************************************************************************
    //
    // Selects the port control value for the GPIO corresponding to SSI FSS pin
    //
    // Depends on: SSI_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: SSI_FSSPIN_CLOCK_ENABLE, SSI_FSSPIN_BASE and SSI_FSSPIN_POS
    //
    //*****************************************************************************
    //#define SSI_FSSPIN_PCTL          0x2
    
    //*****************************************************************************
    //
    // Selects the pin number for the GPIO corresponding to SSI FSS pin
    //
    // Depends on: SSI_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: SSI_FSSPIN_CLOCK_ENABLE, SSI_FSSPIN_BASE and SSI_FSSPIN_PCTL
    //
    //*****************************************************************************
    //#define SSI_FSSPIN_POS          3
    
    //*****************************************************************************
    //
    // Selects the clock enable for the GPIO corresponding to SSI MISO pin
    //
    // Depends on: SSI_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: SSI_MISOPIN_BASE, SSI_MISOPIN_PCTL and SSI_MISOPIN_POS
    //
    //*****************************************************************************
    //#define SSI_MISOPIN_CLOCK_ENABLE          SYSCTL_RCGCGPIO_R0
    
    //*****************************************************************************
    //
    // Selects the base address for the GPIO corresponding to SSI MISO pin
    //
    // Depends on: SSI_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: SSI_MISOPIN_CLOCK_ENABLE, SSI_MISOPIN_PCTL and SSI_MISOPIN_POS
    //
    //*****************************************************************************
    //#define SSI_MISOPIN_BASE          GPIO_PORTA_BASE
    
    //*****************************************************************************
    //
    // Selects the port control value for the GPIO corresponding to SSI MISO pin
    //
    // Depends on: SSI_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: SSI_MISOPIN_CLOCK_ENABLE, SSI_MISOPIN_BASE and SSI_MISOPIN_POS
    //
    //*****************************************************************************
    //#define SSI_MISOPIN_PCTL          0x2
    
    //*****************************************************************************
    //
    // Selects the pin number for the GPIO corresponding to SSI MISO pin
    //
    // Depends on: SSI_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: SSI_MISOPIN_CLOCK_ENABLE, SSI_MISOPIN_BASE and SSI_MISOPIN_PCTL
    //
    //*****************************************************************************
    //#define SSI_MISOPIN_POS          5
    
    //*****************************************************************************
    //
    // Selects the clock enable for the GPIO corresponding to SSI MOSI pin
    //
    // Depends on: SSI_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: SSI_MOSIPIN_BASE, SSI_MOSIPIN_PCTL and SSI_MOSIPIN_POS
    //
    //*****************************************************************************
    //#define SSI_MOSIPIN_CLOCK_ENABLE          SYSCTL_RCGCGPIO_R0
    
    //*****************************************************************************
    //
    // Selects the base address for the GPIO corresponding to SSI MOSI pin
    //
    // Depends on: SSI_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: SSI_MOSIPIN_CLOCK_ENABLE, SSI_MOSIPIN_PCTL and SSI_MOSIPIN_POS
    //
    //*****************************************************************************
    //#define SSI_MOSIPIN_BASE          GPIO_PORTA_BASE
    
    //*****************************************************************************
    //
    // Selects the port control value for the GPIO corresponding to SSI MOSI pin
    //
    // Depends on: SSI_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: SSI_MOSIPIN_CLOCK_ENABLE, SSI_MOSIPIN_BASE and SSI_MOSIPIN_POS
    //
    //*****************************************************************************
    //#define SSI_MOSIPIN_PCTL          0x2
    
    //*****************************************************************************
    //
    // Selects the pin number for the GPIO corresponding to SSI MOSI pin
    //
    // Depends on: SSI_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: SSI_MOSIPIN_CLOCK_ENABLE, SSI_MOSIPIN_BASE and SSI_MOSIPIN_PCTL
    //
    //*****************************************************************************
    //#define SSI_MOSIPIN_POS          4
    
    //*****************************************************************************
    //
    // Selects the I2C port as the port for communicating with the boot loader.
    //
    // Depends on: None
    // Exclusive of: CAN_ENABLE_UPDATE, ENET_ENABLE_UPDATE, SSI_ENABLE_UPDATE,
    //               UART_ENABLE_UPDATE, USB_ENABLE_UPDATE
    // Requires: I2C_SLAVE_ADDR, I2C_CLOCK_ENABLE, I2Cx_BASE, 
    //           I2C_SCLPIN_CLOCK_ENABLE, I2C_SCLPIN_BASE, I2C_SCLPIN_PCTL,
    //           I2C_SCLPIN_POS, I2C_SDAPIN_CLOCK_ENABLE, I2C_SDAPIN_BASE,
    //           I2C_SDAPIN_PCTL and I2C_SDAPIN_POS
    //
    //*****************************************************************************
    //#define I2C_ENABLE_UPDATE
    
    //*****************************************************************************
    //
    // Specifies the I2C address of the boot loader.
    //
    // Depends on: I2C_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define I2C_SLAVE_ADDR          0x42
    
    //*****************************************************************************
    //
    // Selects the clock enable for the I2C peripheral module
    //
    // Depends on: I2C_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: I2Cx_BASE
    //
    //*****************************************************************************
    //#define I2C_CLOCK_ENABLE          SYSCTL_RCGCI2C_R0
    
    //*****************************************************************************
    //
    // Selects the base address of the I2C peripheral module
    //
    // Depends on: I2C_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: I2C_CLOCK_ENABLE
    //
    //*****************************************************************************
    //#define I2Cx_BASE          I2C0_BASE
    //#define I2Cx_BASE			      I2C0_BASE
    
    //*****************************************************************************
    //
    // Selects the clock enable for the GPIO corresponding to I2C SCL pin
    //
    // Depends on: I2C_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: I2C_SCLPIN_BASE, I2C_SCLPIN_PCTL and I2C_SCLPIN_POS
    //
    //*****************************************************************************
    //#define I2C_SCLPIN_CLOCK_ENABLE          SYSCTL_RCGCGPIO_R1
    
    //*****************************************************************************
    //
    // Selects the base address for the GPIO corresponding to I2C SCL pin
    //
    // Depends on: I2C_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: I2C_SCLPIN_CLOCK_ENABLE, I2C_SCLPIN_PCTL and I2C_SCLPIN_POS
    //
    //*****************************************************************************
    //#define I2C_SCLPIN_BASE          GPIO_PORTB_BASE
    
    //*****************************************************************************
    //
    // Selects the port control value for the GPIO corresponding to I2C SCL pin
    //
    // Depends on: I2C_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: I2C_SCLPIN_CLOCK_ENABLE, I2C_SCLPIN_BASE and I2C_SCLPIN_POS
    //
    //*****************************************************************************
    //#define I2C_SCLPIN_PCTL          0x3
    
    //*****************************************************************************
    //
    // Selects the pin number for the GPIO corresponding to I2C SCL pin
    //
    // Depends on: I2C_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: I2C_SCLPIN_CLOCK_ENABLE, I2C_SCLPIN_BASE and I2C_SCLPIN_PCTL
    //
    //*****************************************************************************
    //#define I2C_SCLPIN_POS          2
    
    //*****************************************************************************
    //
    // Selects the clock enable for the GPIO corresponding to I2C SDA pin
    //
    // Depends on: I2C_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: I2C_SDAPIN_BASE, I2C_SDAPIN_PCTL and I2C_SDAPIN_POS
    //
    //*****************************************************************************
    //#define I2C_SDAPIN_CLOCK_ENABLE          SYSCTL_RCGCGPIO_R1
    
    //*****************************************************************************
    //
    // Selects the base address for the GPIO corresponding to I2C SDA pin
    //
    // Depends on: I2C_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: I2C_SDAPIN_CLOCK_ENABLE, I2C_SDAPIN_PCTL and I2C_SDAPIN_POS
    //
    //*****************************************************************************
    //#define I2C_SDAPIN_BASE          GPIO_PORTB_BASE
    
    //*****************************************************************************
    //
    // Selects the port control value for the GPIO corresponding to I2C SDA pin
    //
    // Depends on: I2C_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: I2C_SDAPIN_CLOCK_ENABLE, I2C_SDAPIN_BASE and I2C_SDAPIN_POS
    //
    //*****************************************************************************
    //#define I2C_SDAPIN_PCTL          0x3
    
    //*****************************************************************************
    //
    // Selects the pin number for the GPIO corresponding to I2C SDA pin
    //
    // Depends on: I2C_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: I2C_SDAPIN_CLOCK_ENABLE, I2C_SDAPIN_BASE and I2C_SDAPIN_PCTL
    //
    //*****************************************************************************
    //#define I2C_SDAPIN_POS          3
    
    //*****************************************************************************
    //
    // Selects Ethernet update via the BOOTP/TFTP protocol.
    //
    // Depends on: None
    // Exclusive of: CAN_ENABLE_UPDATE, I2C_ENABLE_UPDATE, SSI_ENABLE_UPDATE,
    //               UART_ENABLE_UPDATE, USB_ENABLE_UPDATE
    // Requires: CRYSTAL_FREQ
    //
    //*****************************************************************************
    #define ENET_ENABLE_UPDATE
    
    //*****************************************************************************
    //
    // Enables the use of the Ethernet status LED outputs to indicate traffic and
    // connection status.
    //
    // Depends on: ENET_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define ENET_ENABLE_LEDS
    
    //*****************************************************************************
    //
    // Specifies the hard coded MAC address for the Ethernet interface.  There are
    // six individual values (ENET_MAC_ADDR0 thru ENET_MAC_ADDR5) that provide
    // the six bytes of the MAC address, where ENET_MAC_ADDR0 thru ENET_MAC_ADDR2
    // provide the organizationally unique identifier (OUI) and ENET_MAC_ADDR3
    // thru ENET_MAC_ADDR5 provide the extension identifier.  If these values
    // are not provided, the MAC address will be extracted from the user registers.
    //
    // Depends on: ENET_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define ENET_MAC_ADDR0          0x00
    //#define ENET_MAC_ADDR1          0x00
    //#define ENET_MAC_ADDR2          0x00
    //#define ENET_MAC_ADDR3          0x00
    //#define ENET_MAC_ADDR4          0x00
    //#define ENET_MAC_ADDR5          0x00
    
    //*****************************************************************************
    //
    // Specifies the name of the BOOTP server from which to request information.
    // The use of this specifier allows a board-specific BOOTP server to co-exist
    // on a network with the DHCP server that may be part of the network
    // infrastructure.  The BOOTP server provided by Texas Instruments requires
    // that this be set to "stellaris".
    //
    // Depends on: ENET_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    #define ENET_BOOTP_SERVER       "tiva"
    
    //*****************************************************************************
    //
    // Selects USB update via Device Firmware Update class.
    //
    // Depends on: None
    // Exclusive of: CAN_ENABLE_UPDATE, ENET_ENABLE_UPDATE, I2C_ENABLE_UPDATE,
    //               SSI_ENABLE_UPDATE, UART_ENABLE_UPDATE,
    // Requires: CRYSTAL_FREQ, USB_VENDOR_ID, USB_PRODUCT_ID, USB_DEVICE_ID,
    //           USB_MAX_POWER
    //
    //*****************************************************************************
    //#define USB_ENABLE_UPDATE
    
    //*****************************************************************************
    //
    // The USB vendor ID published by the DFU device.  This value is the TI
    // Tiva vendor ID.  Change this to the vendor ID you have been assigned by the
    // USB-IF.
    //
    // Depends on: USB_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define USB_VENDOR_ID           0x1cbe
    
    //*****************************************************************************
    //
    // The USB device ID published by the DFU device.  If you are using your own
    // vendor ID, chose a device ID that is different from the ID you use in
    // non-update operation.  If you have sublicensed TI's vendor ID, you must
    // use an assigned product ID here.
    //
    // Depends on: USB_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define USB_PRODUCT_ID          0x00ff
    
    //*****************************************************************************
    //
    // Selects the BCD USB device release number published in the device
    // descriptor.
    //
    // Depends on: USB_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define USB_DEVICE_ID           0x0001
    
    //*****************************************************************************
    //
    // Sets the maximum power consumption that the DFU device will report to the
    // USB host in the configuration descriptor.  Units are milliamps.
    //
    // Depends on: USB_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define USB_MAX_POWER           150
    
    //*****************************************************************************
    //
    // Specifies whether the DFU device reports to the host that it is self-powered
    // (defined as 0) or bus-powered (defined as 1).
    //
    // Depends on: USB_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define USB_BUS_POWERED         1
    
    //*****************************************************************************
    //
    // Specifies whether the target board uses a multiplexer to select between USB
    // host and device modes.
    //
    // Depends on: USB_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: USB_MUX_PERIPH, USB_MUX_PORT, USB_MUX_PIN, USB_MUX_DEVICE
    //
    //*****************************************************************************
    //#define USB_HAS_MUX
    
    //*****************************************************************************
    //
    // Specifies the GPIO peripheral containing the pin which is used to select
    // between USB host and device modes.  The value is of the form
    // SYSCTL_RCGC2_GPIOx, where GPIOx represents the required GPIO port.
    //
    // Depends on: USB_ENABLE_UPDATE, USB_HAS_MUX
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define USB_MUX_PERIPH          SYSCTL_RCGC2_GPIOH
    
    //*****************************************************************************
    //
    // Specifies the GPIO port containing the pin which is used to select between
    // USB host and device modes.  The value is of the form GPIO_PORTx_BASE, where
    // PORTx represents the required GPIO port.
    //
    // Depends on: USB_ENABLE_UPDATE, USB_HAS_MUX
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define USB_MUX_PORT            GPIO_PORTH_BASE
    
    //*****************************************************************************
    //
    // Specifies the GPIO pin number used to select between USB host and device
    // modes.  Valid values are 0 through 7.
    //
    // Depends on: USB_ENABLE_UPDATE, USB_HAS_MUX
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define USB_MUX_PIN             2
    
    //*****************************************************************************
    //
    // Specifies the state of the GPIO pin required to select USB device-mode
    // operation.  Valid values are 0 (low) or 1 (high).
    //
    // Depends on: USB_ENABLE_UPDATE, USB_HAS_MUX
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define USB_MUX_DEVICE          1
    
    //*****************************************************************************
    //
    // Specifies whether the target board requires configuration of the pin used
    // for VBUS.  This applies to Blizzard class and later devices.
    //
    // Depends on: USB_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: USB_VBUS_PERIPH, USB_VBUS_PORT, USB_VBUS_PIN
    //
    //*****************************************************************************
    //#define USB_VBUS_CONFIG
    
    //*****************************************************************************
    //
    // Specifies the GPIO peripheral containing the pin which is used for VBUS.
    // The value is of the form SYSCTL_RCGCGPIO_Rx, where the Rx represents
    // the required GPIO port.  This applies to Blizzard class and later 
    // devices.
    //
    // Depends on: USB_ENABLE_UPDATE, USB_VBUS_CONFIG
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define USB_VBUS_PERIPH          SYSCTL_RCGCGPIO_R1
    
    //*****************************************************************************
    //
    // Specifies the GPIO port containing the pin which is used for VBUS.  The value
    // is of the form GPIO_PORTx_BASE, where PORTx represents the required GPIO
    // port.
    //
    // Depends on: USB_ENABLE_UPDATE, USB_VBUS_CONFIG
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define USB_VBUS_PORT            GPIO_PORTB_BASE
    
    //*****************************************************************************
    //
    // Specifies the GPIO pin number used for VBUS.  Valid values are 0 through 7.
    //
    // Depends on: USB_ENABLE_UPDATE, USB_VBUS_CONFIG
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define USB_VBUS_PIN             1
    
    //*****************************************************************************
    //
    // Specifies whether the target board requires configuration of the pin used
    // for ID.  This applies to Blizzard class and later devices.
    //
    // Depends on: USB_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: USB_ID_PERIPH, USB_ID_PORT, USB_ID_PIN
    //
    //*****************************************************************************
    //#define USB_ID_CONFIG
    
    //*****************************************************************************
    //
    // Specifies the GPIO peripheral containing the pin which is used for ID.
    // The value is of the form SYSCTL_RCGCGPIO_Rx, where the Rx represents
    // the required GPIO port.  This applies to Blizzard class and later 
    // devices.
    //
    // Depends on: USB_ENABLE_UPDATE, USB_ID_CONFIG
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define USB_ID_PERIPH          SYSCTL_RCGCGPIO_R1
    
    //*****************************************************************************
    //
    // Specifies the GPIO port containing the pin which is used for ID.  The value
    // is of the form GPIO_PORTx_BASE, where PORTx represents the required GPIO
    // port.
    //
    // Depends on: USB_ENABLE_UPDATE, USB_ID_CONFIG
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define USB_ID_PORT            GPIO_PORTB_BASE
    
    //*****************************************************************************
    //
    // Specifies the GPIO pin number used for ID.  Valid values are 0 through 7.
    //
    // Depends on: USB_ENABLE_UPDATE, USB_ID_CONFIG
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define USB_ID_PIN             0
    
    //*****************************************************************************
    //
    // Specifies whether the target board requires configuration of the pin used
    // for DP.  This applies to Blizzard class and later devices.
    //
    // Depends on: USB_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: USB_DP_PERIPH, USB_DP_PORT, USB_DP_PIN
    //
    //*****************************************************************************
    //#define USB_DP_CONFIG
    
    //*****************************************************************************
    //
    // Specifies the GPIO peripheral containing the pin which is used for DP.
    // The value is of the form SYSCTL_RCGCGPIO_Rx, where the Rx represents
    // the required GPIO port.  This applies to Blizzard class and later 
    // devices.
    //
    // Depends on: USB_ENABLE_UPDATE, USB_DP_CONFIG
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define USB_DP_PERIPH          SYSCTL_RCGCGPIO_R10            // For EK-TM4C1294XL
    //#define USB_DP_PERIPH          SYSCTL_RCGCGPIO_R3            // For EK-TM4C123GXL
    
    //*****************************************************************************
    //
    // Specifies the GPIO port containing the pin which is used for DP.  The value
    // is of the form GPIO_PORTx_BASE, where PORTx represents the required GPIO
    // port.
    //
    // Depends on: USB_ENABLE_UPDATE, USB_DP_CONFIG
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define USB_DP_PORT            GPIO_PORTL_BASE            // For EK-TM4C1294XL
    //#define USB_DP_PORT            GPIO_PORTD_BASE            // For EK-TM4C1294XL
    
    //*****************************************************************************
    //
    // Specifies the GPIO pin number used for DP.  Valid values are 0 through 7.
    //
    // Depends on: USB_ENABLE_UPDATE, USB_DP_CONFIG
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define USB_DP_PIN             6            // For EK-TM4C1294XL
    //#define USB_DP_PIN             5            // For EK-TM4C123GXL
    
    //*****************************************************************************
    //
    // Specifies whether the target board requires configuration of the pin used
    // for DM.  This applies to Blizzard class and later devices.
    //
    // Depends on: USB_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: USB_DM_PERIPH, USB_DM_PORT, USB_DM_PIN
    //
    //*****************************************************************************
    //#define USB_DM_CONFIG
    
    //*****************************************************************************
    //
    // Specifies the GPIO peripheral containing the pin which is used for DM.
    // The value is of the form SYSCTL_RCGCGPIO_Rx, where the Rx represents
    // the required GPIO port.  This applies to Blizzard class and later 
    // devices.
    //
    // Depends on: USB_ENABLE_UPDATE, USB_DM_CONFIG
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define USB_DM_PERIPH          SYSCTL_RCGCGPIO_R10            // For EK-TM4C1294XL
    //#define USB_DM_PERIPH          SYSCTL_RCGCGPIO_R3            // For EK-TM4C123GXL
    
    //*****************************************************************************
    //
    // Specifies the GPIO port containing the pin which is used for DM.  The value
    // is of the form GPIO_PORTx_BASE, where PORTx represents the required GPIO
    // port.
    //
    // Depends on: USB_ENABLE_UPDATE, USB_DM_CONFIG
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define USB_DM_PORT            GPIO_PORTL_BASE            // For EK-TM4C1294XL
    //#define USB_DM_PORT            GPIO_PORTD_BASE            // For EK-TM4C123GXL
    
    //*****************************************************************************
    //
    // Specifies the GPIO pin number used for DM.  Valid values are 0 through 7.
    //
    // Depends on: USB_ENABLE_UPDATE, USB_DM_CONFIG
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define USB_DM_PIN             7            // For EK-TM4C1294XL
    //#define USB_DM_PIN             4            // For EK-TM4C123GXL
    
    //*****************************************************************************
    //
    // Selects an update via the CAN port.
    //
    // Depends on: None
    // Exclusive of: ENET_ENABLE_UPDATE, I2C_ENABLE_UPDATE, SSI_ENABLE_UPDATE,
    //               UART_ENABLE_UPDATE, USB_ENABLE_UPDATE
    // Requires: CAN_RX_PERIPH, CAN_RX_PORT, CAN_RX_PIN, CAN_TX_PERIPH,
    //           CAN_TX_PORT, CAN_TX_PIN, CAN_BIT_RATE, CRYSTAL_FREQ.
    //
    //*****************************************************************************
    //#define CAN_ENABLE_UPDATE
    
    //*****************************************************************************
    //
    // Enables the UART to CAN bridging for use when the CAN port is selected for
    // communicating with the boot loader.
    //
    // Depends on: CAN_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define CAN_UART_BRIDGE
    
    //*****************************************************************************
    //
    // The GPIO module to enable in order to configure the CAN0 Rx pin.  This will
    // be one of the SYSCTL_RCGC2_GPIOx values, where "x" is replaced with the port
    // name (such as B).  The value of "x" should match the value of "x" for
    // CAN_RX_PORT.
    //
    // Depends on: CAN_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define CAN_RX_PERIPH           SYSCTL_RCGC2_GPIOA
    
    //*****************************************************************************
    //
    // The GPIO port used to configure the CAN0 Rx pin.  This will be one of the
    // GPIO_PORTx_BASE values, where "x" is replaced with the port name (such as
    // B).  The value of "x" should match the value of "x" for CAN_RX_PERIPH.
    //
    // Depends on: CAN_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define CAN_RX_PORT             GPIO_PORTA_BASE
    
    //*****************************************************************************
    //
    // The GPIO pin that is shared with the CAN0 Rx pin.  This is a value between 0
    // and 7.
    //
    // Depends on: CAN_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define CAN_RX_PIN              0
    
    //*****************************************************************************
    //
    // The GPIO module to enable in order to configure the CAN0 Tx pin.  This will
    // be one of the SYSCTL_RCGC2_GPIOx values, where "x" is replaced with the port
    // name (such as B).  The value of "x" should match the value of "x" for
    // CAN_TX_PORT.
    //
    // Depends on: CAN_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define CAN_TX_PERIPH           SYSCTL_RCGC2_GPIOA
    
    //*****************************************************************************
    //
    // The GPIO port used to configure the CAN0 Tx pin.  This will be one of the
    // GPIO_PORTx_BASE values, where "x" is replaced with the port name (such as
    // B).  The value of "x" should match the value of "x" for CAN_TX_PERIPH.
    //
    // Depends on: CAN_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define CAN_TX_PORT             GPIO_PORTA_BASE
    
    //*****************************************************************************
    //
    // The GPIO pin that is shared with the CAN0 Tx pin.  This is a value between 0
    // and 7.
    //
    // Depends on: CAN_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define CAN_TX_PIN              1
    
    //*****************************************************************************
    //
    // The bit rate used on the CAN bus.  This must be one of 20000, 50000, 125000,
    // 250000, 500000, or 1000000.  The CAN bit rate must be less than or equal to
    // the crystal frequency divided by 8 (CRYSTAL_FREQ / 8).
    //
    // Depends on: CAN_ENABLE_UPDATE
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    //#define CAN_BIT_RATE            1000000
    
    //*****************************************************************************
    //
    // Performs application-specific low level hardware initialization on system
    // reset.  If hooked, this function will be called immediately after the boot
    // loader code relocation completes.  An application may perform any required
    // low-level hardware initialization during this function.  Note that the
    // system clock has not been set when this function is called.  Initialization
    // that assumes the system clock is set may be performed in the BL_INIT_FN_HOOK
    // function instead.
    //
    // void MyHwInitFunc(void);
    //
    //*****************************************************************************
    //#define BL_HW_INIT_FN_HOOK      MyHwInitFunc
    
    //*****************************************************************************
    //
    // Performs application-specific initialization on system reset.  If hooked,
    // this function will be called during boot loader initialization to perform
    // any board- or application-specific initialization which is required.  The
    // function is called following a reset immediately after the selected boot
    // loader peripheral has been configured and the system clock has been set.
    //
    // void MyInitFunc(void);
    //
    //*****************************************************************************
    //#define BL_INIT_FN_HOOK         MyInitFunc
    
    //*****************************************************************************
    //
    // Performs application-specific reinitialization on boot loader entry via SVC.
    // If hooked, this function will be called during boot loader reinitialization
    // to perform any board- or application-specific initialization which is
    // required.  The function is called following boot loader entry from an
    // application, after any system clock rate adjustments have been made.
    //
    // void MyReinitFunc(void);
    //
    //*****************************************************************************
    //#define BL_REINIT_FN_HOOK       MyReinitFunc
    
    //*****************************************************************************
    //
    // Informs an application that a download is starting.  If hooked, this
    // function will be called when a firmware download is about to begin.  The
    // function is called after the first data packet of the download is received
    // but before it has been written to flash.
    //
    // void MyStartFunc(void);
    //
    //*****************************************************************************
    //#define BL_START_FN_HOOK        MyStartFunc
    
    //*****************************************************************************
    //
    // Informs an application of download progress.  If hooked, this function will
    // be called periodically during a firmware download to provide progress
    // information.  The function is called after each data packet is received from
    // the host.  Parameters provide the number of bytes of data received and, in
    // cases other than Ethernet update, the expected total number of bytes in the
    // download (the TFTP protocol used by the Ethernet boot loader does not send
    // the final image size before the download starts so in this case the ulTotal
    // parameter is set to 0 to indicate that the size is unknown).
    //
    // void MyProgressFunc(unsigned long ulCompleted, unsigned long ulTotal);
    //
    //*****************************************************************************
    //#define BL_PROGRESS_FN_HOOK     MyProgressFunc
    
    //*****************************************************************************
    //
    // Informs an application that a download has completed.  If hooked, this
    // function will be called when a firmware download has just completed.  The
    // function is called after the final data packet of the download has been
    // written to flash.
    //
    // void MyEndFunc(void);
    //
    //*****************************************************************************
    //#define BL_END_FN_HOOK          MyEndFunc
    
    //*****************************************************************************
    //
    // Allows an application to perform in-place data decryption during download.
    // If hooked, this function will be called to perform in-place decryption of
    // each data packet received during a firmware download.
    //
    // void MyDecryptionFunc(unsigned char *pucBuffer, unsigned long ulSize);
    //
    // This value takes precedence over ENABLE_DECRYPTION.  If both are defined,
    // the hook function defined using BL_DECRYPT_FN_HOOK is called rather than the
    // previously-defined DecryptData() stub function.
    //
    //*****************************************************************************
    //#define BL_DECRYPT_FN_HOOK      MyDecryptionFunc
    
    //*****************************************************************************
    //
    // Allows an application to force a new firmware download.  If hooked, this
    // function will be called during boot loader initialization to determine
    // whether a firmware update should be performed regardless of whether a valid
    // main code image is already present.  If the function returns 0, the existing
    // main code image is booted (if present), otherwise the boot loader will wait
    // for a new firmware image to be downloaded.
    //
    // unsigned long MyCheckUpdateFunc(void);
    //
    // This value takes precedence over ENABLE_UPDATE_CHECK} if both are defined.
    // If you wish to perform a GPIO check in addition to any other update check
    // processing required, the GPIO code must be included within the hook function
    // itself.
    //
    //*****************************************************************************
    //#define BL_CHECK_UPDATE_FN_HOOK MyCheckUpdateFunc
    
    //*****************************************************************************
    //
    // Allows an application to replace the flash block erase function.  If hooked,
    // this function will be called whenever a block of flash is to be erased.  The
    // function must erase the block and wait until the operation has completed.
    // The size of the block which will be erased is defined by FLASH_BLOCK_SIZE.
    //
    // void MyFlashEraseFunc(unsigned long ulBlockAddr);
    //
    //*****************************************************************************
    //#define BL_FLASH_ERASE_FN_HOOK  MyFlashEraseFunc
    
    //*****************************************************************************
    //
    // Allows an application to replace the flash programming function.  If hooked,
    // this function will be called to program the flash with firmware image data
    // received during download operations.  The function must program the supplied
    // data and wait until the operation has completed.
    //
    // void MyFlashProgramFunc(unsigned long ulDstAddr,
    //                         unsigned char *pucSrcData,
    //                         unsigned long ulLength);
    //
    //*****************************************************************************
    //#define BL_FLASH_PROGRAM_FN_HOOK MyFlashProgramFunc
    
    //*****************************************************************************
    //
    // Allows an application to replace the flash error clear function.  If hooked,
    // this function must clear any flash error indicators and prepare to detect
    // access violations that may occur in a future erase or program operations.
    //
    // void MyFlashClearErrorFunc(void);
    //
    //*****************************************************************************
    //#define BL_FLASH_CL_ERR_FN_HOOK MyFlashClearErrorFunc
    
    //*****************************************************************************
    //
    // Reports whether or not a flash access violation error has occurred.  If
    // hooked, this function will be called after flash erase or program
    // operations.  The return code indicates whether or not an access violation
    // error occurred since the last call to the function defined by
    // BL_FLASH_CL_ERR_FN_HOOK, with 0 indicating no errors and non-zero indicating
    // an error.
    //
    // unsigned long MyFlashErrorFunc(void);
    //
    //*****************************************************************************
    //#define BL_FLASH_ERROR_FN_HOOK  MyFlashErrorFunc
    
    //*****************************************************************************
    //
    // Reports the total size of the device flash.  If hooked, this function will
    // be called to determine the size of the supported flash device.  The return
    // code is the number of bytes of flash in the device.  Note that this does not
    // take into account any reserved space defined via the FLASH_RSVD_SPACE value.
    //
    // unsigned long MyFlashSizeFunc(void);
    //
    //*****************************************************************************
    //#define BL_FLASH_SIZE_FN_HOOK   MyFlashSizeFunc
    
    //*****************************************************************************
    //
    // Reports the address of the first byte after the end of the device flash.  If
    // hooked, this function will be called to determine the address of the end of
    // valid flash.  Note that this does not take into account any reserved space
    // defined via the FLASH_RSVD_SPACE value.
    //
    // unsigned long MyFlashEndFunc(void);
    //
    //*****************************************************************************
    //#define BL_FLASH_END_FN_HOOK    MyFlashEndFunc
    
    //*****************************************************************************
    //
    // Checks whether the start address and size of an image are valid.  If hooked,
    // this function will be called when a new firmware download is about to start.
    // Parameters provided are the requested start address for the new download
    // and, when using protocols which transmit the image length in advance, the
    // size of the image that is to be downloaded.  The return code will be
    // non-zero to indicate that the start address is valid and the image will fit
    // in the available space, or 0 if either the address is invalid or the image
    // is too large for the device.
    //
    // unsigned long MyFlashAddrCheckFunc(unsigned long ulAddr,
    //                                    unsigned long ulSize);
    //
    //*****************************************************************************
    //#define BL_FLASH_AD_CHECK_FN_HOOK MyFlashAddrCheckFunc
    
    #endif // __BL_CONFIG_H__
    

    bl_config.h

  • Did you try the example as-is without modification? There is no need to modify the example as it should work out of the box.

    How many NICs (network interface controller) are there on your PC? If you have multiple of them installed on your PC then you need to disable all except the one that is acting as the BootP and TFTP server talking to the client (your MCU). When I look at your video, you seem to have two of them Ethernet Adapter selection when you open LM Flash Programmer. 

  • I used the example code without any modification but still i have the same problem and I disabled all the NIC cards except the PC ethernet also I can share the Wireshark logs  if needed

  • Iam also getting this 3 warning do i need to enable these things ?

  • IS it possible to add uart prints for debugging purpose in boot_emac_flash project 

  • I used the example code without any modification but still i have the same problem and I disabled all the NIC cards except the PC ethernet also I can share the Wireshark logs  if needed

    Are you running on a LaunchPad or you own board? If you are running on your own board, do you have a valid MAC address?

    Iam also getting this 3 warning do i need to enable these things ?

    What compiler version are you using? I just rebuilt the example with the default settings and I don't see any warning. 

    **** Clean-only build of configuration Debug for project boot_emac_flash ****
    
    "C:\\ti\\ccs1011\\ccs\\utils\\bin\\gmake" -k -j 8 clean -O 
     
    gmake: *** No rule to make target 'clean'.
    
    **** Build Finished ****
    
    **** Build of configuration Debug for project boot_emac_flash ****
    
    "C:\\ti\\ccs1011\\ccs\\utils\\bin\\gmake" -k -j 8 all -O 
     
    Building file: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_autobaud.c"
    Invoking: ARM Compiler
    "C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/bin/armcl" -mv7M4 --code_state=16 --float_support=FPv4SPD16 -me -O2 --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader" --include_path="C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/include" --define=ccs="ccs" --define=PART_TM4C1294NCPDT --define=TARGET_IS_TM4C129_RA2 -g --gcc --diag_warning=225 --diag_wrap=off --display_error_number --gen_func_subsections=on --abi=eabi --ual --preproc_with_compile --preproc_dependency="boot_loader/bl_autobaud.d_raw" --obj_directory="boot_loader"  "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_autobaud.c"
    Finished building: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_autobaud.c"
     
    Building file: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_can.c"
    Invoking: ARM Compiler
    "C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/bin/armcl" -mv7M4 --code_state=16 --float_support=FPv4SPD16 -me -O2 --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader" --include_path="C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/include" --define=ccs="ccs" --define=PART_TM4C1294NCPDT --define=TARGET_IS_TM4C129_RA2 -g --gcc --diag_warning=225 --diag_wrap=off --display_error_number --gen_func_subsections=on --abi=eabi --ual --preproc_with_compile --preproc_dependency="boot_loader/bl_can.d_raw" --obj_directory="boot_loader"  "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_can.c"
    Finished building: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_can.c"
     
    Building file: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_check.c"
    Invoking: ARM Compiler
    "C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/bin/armcl" -mv7M4 --code_state=16 --float_support=FPv4SPD16 -me -O2 --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader" --include_path="C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/include" --define=ccs="ccs" --define=PART_TM4C1294NCPDT --define=TARGET_IS_TM4C129_RA2 -g --gcc --diag_warning=225 --diag_wrap=off --display_error_number --gen_func_subsections=on --abi=eabi --ual --preproc_with_compile --preproc_dependency="boot_loader/bl_check.d_raw" --obj_directory="boot_loader"  "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_check.c"
    Finished building: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_check.c"
     
    Building file: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_crc32.c"
    Invoking: ARM Compiler
    "C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/bin/armcl" -mv7M4 --code_state=16 --float_support=FPv4SPD16 -me -O2 --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader" --include_path="C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/include" --define=ccs="ccs" --define=PART_TM4C1294NCPDT --define=TARGET_IS_TM4C129_RA2 -g --gcc --diag_warning=225 --diag_wrap=off --display_error_number --gen_func_subsections=on --abi=eabi --ual --preproc_with_compile --preproc_dependency="boot_loader/bl_crc32.d_raw" --obj_directory="boot_loader"  "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_crc32.c"
    Finished building: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_crc32.c"
     
    Building file: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_decrypt.c"
    Invoking: ARM Compiler
    "C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/bin/armcl" -mv7M4 --code_state=16 --float_support=FPv4SPD16 -me -O2 --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader" --include_path="C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/include" --define=ccs="ccs" --define=PART_TM4C1294NCPDT --define=TARGET_IS_TM4C129_RA2 -g --gcc --diag_warning=225 --diag_wrap=off --display_error_number --gen_func_subsections=on --abi=eabi --ual --preproc_with_compile --preproc_dependency="boot_loader/bl_decrypt.d_raw" --obj_directory="boot_loader"  "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_decrypt.c"
    Finished building: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_decrypt.c"
     
    Building file: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_flash.c"
    Invoking: ARM Compiler
    "C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/bin/armcl" -mv7M4 --code_state=16 --float_support=FPv4SPD16 -me -O2 --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader" --include_path="C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/include" --define=ccs="ccs" --define=PART_TM4C1294NCPDT --define=TARGET_IS_TM4C129_RA2 -g --gcc --diag_warning=225 --diag_wrap=off --display_error_number --gen_func_subsections=on --abi=eabi --ual --preproc_with_compile --preproc_dependency="boot_loader/bl_flash.d_raw" --obj_directory="boot_loader"  "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_flash.c"
    Finished building: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_flash.c"
     
    Building file: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_emac.c"
    Invoking: ARM Compiler
    "C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/bin/armcl" -mv7M4 --code_state=16 --float_support=FPv4SPD16 -me -O2 --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader" --include_path="C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/include" --define=ccs="ccs" --define=PART_TM4C1294NCPDT --define=TARGET_IS_TM4C129_RA2 -g --gcc --diag_warning=225 --diag_wrap=off --display_error_number --gen_func_subsections=on --abi=eabi --ual --preproc_with_compile --preproc_dependency="boot_loader/bl_emac.d_raw" --obj_directory="boot_loader"  "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_emac.c"
    Finished building: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_emac.c"
     
    Building file: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_i2c.c"
    Invoking: ARM Compiler
    "C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/bin/armcl" -mv7M4 --code_state=16 --float_support=FPv4SPD16 -me -O2 --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader" --include_path="C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/include" --define=ccs="ccs" --define=PART_TM4C1294NCPDT --define=TARGET_IS_TM4C129_RA2 -g --gcc --diag_warning=225 --diag_wrap=off --display_error_number --gen_func_subsections=on --abi=eabi --ual --preproc_with_compile --preproc_dependency="boot_loader/bl_i2c.d_raw" --obj_directory="boot_loader"  "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_i2c.c"
    Finished building: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_i2c.c"
     
    Building file: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_main.c"
    Invoking: ARM Compiler
    "C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/bin/armcl" -mv7M4 --code_state=16 --float_support=FPv4SPD16 -me -O2 --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader" --include_path="C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/include" --define=ccs="ccs" --define=PART_TM4C1294NCPDT --define=TARGET_IS_TM4C129_RA2 -g --gcc --diag_warning=225 --diag_wrap=off --display_error_number --gen_func_subsections=on --abi=eabi --ual --preproc_with_compile --preproc_dependency="boot_loader/bl_main.d_raw" --obj_directory="boot_loader"  "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_main.c"
    Finished building: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_main.c"
     
    Building file: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_packet.c"
    Invoking: ARM Compiler
    "C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/bin/armcl" -mv7M4 --code_state=16 --float_support=FPv4SPD16 -me -O2 --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader" --include_path="C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/include" --define=ccs="ccs" --define=PART_TM4C1294NCPDT --define=TARGET_IS_TM4C129_RA2 -g --gcc --diag_warning=225 --diag_wrap=off --display_error_number --gen_func_subsections=on --abi=eabi --ual --preproc_with_compile --preproc_dependency="boot_loader/bl_packet.d_raw" --obj_directory="boot_loader"  "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_packet.c"
    Finished building: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_packet.c"
     
    Building file: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_ssi.c"
    Invoking: ARM Compiler
    "C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/bin/armcl" -mv7M4 --code_state=16 --float_support=FPv4SPD16 -me -O2 --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader" --include_path="C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/include" --define=ccs="ccs" --define=PART_TM4C1294NCPDT --define=TARGET_IS_TM4C129_RA2 -g --gcc --diag_warning=225 --diag_wrap=off --display_error_number --gen_func_subsections=on --abi=eabi --ual --preproc_with_compile --preproc_dependency="boot_loader/bl_ssi.d_raw" --obj_directory="boot_loader"  "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_ssi.c"
    Finished building: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_ssi.c"
     
    Building file: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_startup_ccs.s"
    Invoking: ARM Compiler
    "C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/bin/armcl" -mv7M4 --code_state=16 --float_support=FPv4SPD16 -me -O2 --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader" --include_path="C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/include" --define=ccs="ccs" --define=PART_TM4C1294NCPDT --define=TARGET_IS_TM4C129_RA2 -g --gcc --diag_warning=225 --diag_wrap=off --display_error_number --gen_func_subsections=on --abi=eabi --ual --preproc_with_compile --preproc_dependency="boot_loader/bl_startup_ccs.d_raw" --obj_directory="boot_loader"  "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_startup_ccs.s"
    Finished building: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_startup_ccs.s"
     
    Building file: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_uart.c"
    Invoking: ARM Compiler
    "C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/bin/armcl" -mv7M4 --code_state=16 --float_support=FPv4SPD16 -me -O2 --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader" --include_path="C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/include" --define=ccs="ccs" --define=PART_TM4C1294NCPDT --define=TARGET_IS_TM4C129_RA2 -g --gcc --diag_warning=225 --diag_wrap=off --display_error_number --gen_func_subsections=on --abi=eabi --ual --preproc_with_compile --preproc_dependency="boot_loader/bl_uart.d_raw" --obj_directory="boot_loader"  "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_uart.c"
    Finished building: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_uart.c"
     
    Building file: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_usb.c"
    Invoking: ARM Compiler
    "C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/bin/armcl" -mv7M4 --code_state=16 --float_support=FPv4SPD16 -me -O2 --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader" --include_path="C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/include" --define=ccs="ccs" --define=PART_TM4C1294NCPDT --define=TARGET_IS_TM4C129_RA2 -g --gcc --diag_warning=225 --diag_wrap=off --display_error_number --gen_func_subsections=on --abi=eabi --ual --preproc_with_compile --preproc_dependency="boot_loader/bl_usb.d_raw" --obj_directory="boot_loader"  "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_usb.c"
    Finished building: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_usb.c"
     
    Building file: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_usbfuncs.c"
    Invoking: ARM Compiler
    "C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/bin/armcl" -mv7M4 --code_state=16 --float_support=FPv4SPD16 -me -O2 --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/Users/a0321879/Documents/CCS/TM4C/My CCS EKTM4C1294XL 2.2.0/boot_emac_flash" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295" --include_path="C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader" --include_path="C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/include" --define=ccs="ccs" --define=PART_TM4C1294NCPDT --define=TARGET_IS_TM4C129_RA2 -g --gcc --diag_warning=225 --diag_wrap=off --display_error_number --gen_func_subsections=on --abi=eabi --ual --preproc_with_compile --preproc_dependency="boot_loader/bl_usbfuncs.d_raw" --obj_directory="boot_loader"  "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_usbfuncs.c"
    Finished building: "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_usbfuncs.c"
     
    Building target: "boot_emac_flash.out"
    Invoking: ARM Linker
    "C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/bin/armcl" -mv7M4 --code_state=16 --float_support=FPv4SPD16 -me -O2 --define=ccs="ccs" --define=PART_TM4C1294NCPDT --define=TARGET_IS_TM4C129_RA2 -g --gcc --diag_warning=225 --diag_wrap=off --display_error_number --gen_func_subsections=on --abi=eabi --ual -z -m"boot_emac_flash_ccs.map" --heap_size=0 --stack_size=1024 -i"C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/lib" -i"C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/include" --reread_libs --diag_wrap=off --display_error_number --warn_sections --xml_link_info="boot_emac_flash_linkInfo.xml" --ram_model -o "boot_emac_flash.out" "./boot_loader/bl_autobaud.obj" "./boot_loader/bl_can.obj" "./boot_loader/bl_check.obj" "./boot_loader/bl_crc32.obj" "./boot_loader/bl_decrypt.obj" "./boot_loader/bl_emac.obj" "./boot_loader/bl_flash.obj" "./boot_loader/bl_i2c.obj" "./boot_loader/bl_main.obj" "./boot_loader/bl_packet.obj" "./boot_loader/bl_ssi.obj" "./boot_loader/bl_startup_ccs.obj" "./boot_loader/bl_uart.obj" "./boot_loader/bl_usb.obj" "./boot_loader/bl_usbfuncs.obj" "C:/ti/TivaWare_C_Series-2.2.0.295/boot_loader/bl_link_ccs.cmd"  -l"C:/ti/TivaWare_C_Series-2.2.0.295/driverlib/ccs/Debug/driverlib.lib" -llibc.a 
    <Linking>
    Finished building target: "boot_emac_flash.out"
     
    "C:/ti/ccs1011/ccs/utils/tiobj2bin/tiobj2bin" "boot_emac_flash.out" "boot_emac_flash.bin" "C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/bin/armofd" "C:/ti/ccs1011/ccs/tools/compiler/ti_cgt-arm_18.12.0.LTS/bin/armhex" "C:/ti/ccs1011/ccs/utils/tiobj2bin/mkhex4bin"
     
    
    **** Build Finished ****
    

    IS it possible to add uart prints for debugging purpose in boot_emac_flash project 

    It is possible but I will suggest you look at the wireshark instead. Do you see the bootloader send out the BOOTP request? Why don't you show your wireshark capture?

  • How can I upload the wireshark logs , could not able to upload it as a file and

    how to configure the boot_emac_flash project as static and without BOOTP request and reply and directly using TFTP ? 

  • How can I upload the wireshark logs , could not able to upload it as a file and

    You just drag the file into the forum editor window. 

    how to configure the boot_emac_flash project as static and without BOOTP request and reply and directly using TFTP ? 

    The example bootloader uses the BOOTP protocol to establish connection between a client and server before TFTP can start. Check this article for clarification. https://www.techtarget.com/searchnetworking/definition/BOOTP. I will suggest you get the existing example working first before you venture into making some custom bootloader without using BOOTP. 

  • Hi charles 

    At-last it got worked after changing the stack size from 256 to 1024 in bl_config.h
    can you please suggest code changes for how to use this project with static IP with only TFTP and without BOOTP protocol


  • At-last it got worked after changing the stack size from 256 to 1024 in bl_config.h

    Hi,

      When I check the default CCS project setting for boot_emac_flash, the stack size is 1024 being reserved. Did you happen to change this value? In anycase, glad your problem is resolved. 

    can you please suggest code changes for how to use this project with static IP with only TFTP and without BOOTP protocol

    If you already know a static IP that is available on your network, you can just use that IP address in LM Flash Programmer setting. The reason I asked you to first run enet_lwip example was that the DHCP server will give you an available IP address. That address is normally leased to the client for a while. It could be hours, days or indefinite depending on your network setting. Since that DHCP address is leased to you, you can use that address to enter to the LM flash programmer. But if you already know for sure that a particular IP address is not used/leased to any node on your network then you could just use that address for the client along with the client's MAC address and enter the pair into LM flash programmer. 

  • Hi Charles

    If you already know a static IP that is available on your network, you can just use that IP address in LM Flash Programmer setting. 

    means I can use any ip address in LM flash which will be configured as static

    can you please elaborate how to configure a static IP & to Remove BOOTP request & reply

  • means I can use any ip address in LM flash which will be configured as static

    Again, any IP address that you know for sure is not used/assigned to any node on your network. You need to talk to your IT department what are the available IP addresses that can be used statically. If you are on your home network, you normally can log in to your router and find our what addresses have been used already. 

    can you please elaborate how to configure a static IP & to Remove BOOTP request & reply

    I don't understand your question. How can you remove BOOTP for the purpose of bootloading? The BOOTP is the protocol to download/update a new firmware through Ethernet interface. 

  • Hi Charles 
    Is BOOTP & DHCP are same or different  I need either DHCP or Static IP need to be enabled , can you help me for code changes ?

  • Is BOOTP & DHCP are same or different  I need either DHCP or Static IP need to be enabled , can you help me for code changes ?

    Why don't you read about the difference between BOOTP and DHCP? This article will be helpful. https://www.tutorialspoint.com/difference-between-bootp-and-dhcp

    What are you trying to achieve? I thought you were trying to use a Ethernet bootloader to download/update firmware on the flash. Isn't that what you want to do? A bootloader is supposed to be a very small program residing on the flash to perform such task. The current example uses BOOTP because it is small to implement. DHCP is a layer-7 protocol which means it is an application in the definition of OSI model. To implement DHCP you would need to have the TCP/IP stack running. Check the enet_lwip example where DHCP is used and the lwIP (TCP/IP) stack is loaded to handle the layer 2 and layer 3 operations. It will take up a huge amount of memory just to acquire an IP address. Is that what you really want?