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.

TM4C129ENCPDT: Programmatically changing the MAC address

Part Number: TM4C129ENCPDT
Other Parts Discussed in Thread: SEGGER, SYSBIOS, UNIFLASH, EK-TM4C1294XL,

Tool/software:

Hello,

I am using the TIRTOS tcpEcho example project. I have a black MCU, which is part of Mikroe's TIVA module (https://www.mikroe.com/mcu-card-3-for-tiva-tm4c129encpdt).

I am using a Segger J-link as an external programmer.

Is there a way to program the MAC in code? I am trying to use EMACAddrSet function. Here is a dump of my tcpEcho.c, and my changes are prefaced by "//NM":

/*
 * Copyright (c) 2014-2015, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 *    ======== tcpEcho.c ========
 *    Contains BSD sockets code.
 */

#include <string.h>

#include <xdc/std.h>
#include <xdc/runtime/Error.h>
#include <xdc/runtime/System.h>

#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/drivers/GPIO.h>

//NM
#include <driverlib/emac.h>

/* NDK BSD support */
#include <sys/socket.h>

/* Example/Board Header file */
#include "Board.h"

#define TCPPACKETSIZE 256
#define NUMTCPWORKERS 3

/*
 *  ======== tcpWorker ========
 *  Task to handle TCP connection. Can be multiple Tasks running
 *  this function.
 */
Void tcpWorker(UArg arg0, UArg arg1)
{
    int  clientfd = (int)arg0;
    int  bytesRcvd;
    int  bytesSent;
    char buffer[TCPPACKETSIZE];

    System_printf("tcpWorker: start clientfd = 0x%x\n", clientfd);

    while ((bytesRcvd = recv(clientfd, buffer, TCPPACKETSIZE, 0)) > 0) {
        bytesSent = send(clientfd, buffer, bytesRcvd, 0);
        if (bytesSent < 0 || bytesSent != bytesRcvd) {
            System_printf("Error: send failed.\n");
            break;
        }
    }
    System_printf("tcpWorker stop clientfd = 0x%x\n", clientfd);

    close(clientfd);
}

/*
 *  ======== tcpHandler ========
 *  Creates new Task to handle new TCP connections.
 */
Void tcpHandler(UArg arg0, UArg arg1)
{
    int                status;
    int                clientfd;
    int                server;
    struct sockaddr_in localAddr;
    struct sockaddr_in clientAddr;
    int                optval;
    int                optlen = sizeof(optval);
    socklen_t          addrlen = sizeof(clientAddr);
    Task_Handle        taskHandle;
    Task_Params        taskParams;
    Error_Block        eb;

    server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (server == -1) {
        System_printf("Error: socket not created.\n");
        goto shutdown;
    }


    memset(&localAddr, 0, sizeof(localAddr));
    localAddr.sin_family = AF_INET;
    localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    localAddr.sin_port = htons(arg0);

    status = bind(server, (struct sockaddr *)&localAddr, sizeof(localAddr));
    if (status == -1) {
        System_printf("Error: bind failed.\n");
        goto shutdown;
    }

    status = listen(server, NUMTCPWORKERS);
    if (status == -1) {
        System_printf("Error: listen failed.\n");
        goto shutdown;
    }

    optval = 1;
    if (setsockopt(server, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0) {
        System_printf("Error: setsockopt failed\n");
        goto shutdown;
    }

    while ((clientfd =
            accept(server, (struct sockaddr *)&clientAddr, &addrlen)) != -1) {

        System_printf("tcpHandler: Creating thread clientfd = %d\n", clientfd);

        /* Init the Error_Block */
        Error_init(&eb);

        /* Initialize the defaults and set the parameters. */
        Task_Params_init(&taskParams);
        taskParams.arg0 = (UArg)clientfd;
        taskParams.stackSize = 1280;
        taskHandle = Task_create((Task_FuncPtr)tcpWorker, &taskParams, &eb);
        if (taskHandle == NULL) {
            System_printf("Error: Failed to create new Task\n");
            close(clientfd);
        }

        /* addrlen is a value-result param, must reset for next accept call */
        addrlen = sizeof(clientAddr);
    }

    System_printf("Error: accept failed.\n");

shutdown:
    if (server > 0) {
        close(server);
    }
}

/*
 *  ======== main ========
 */
int main(void)
{

//NM
    static const uint8_t macArray[6] = {0xAC,0xDE,0x48,0x00,0x00,0x80};
   

/* Call board init functions */
    Board_initGeneral();
    Board_initGPIO();

    //NM
    EMACAddrSet(0x400EC000,0, macArray);

    Board_initEMAC();

    System_printf("Starting the TCP Echo example\nSystem provider is set to "
                  "SysMin. Halt the target to view any SysMin contents in"
                  " ROV.\n");
    /* SysMin will only print to the console when you call flush or exit */
    System_flush();

    /* Start BIOS */
    BIOS_start();

    return (0);
}

These changes result in a compiler error:

"C:/ti/tirtos_tivac_2_16_01_14/products/TivaWare_C_Series-2.1.1.71b/driverlib/emac.h", line 959: error #20: identifier "bool" is undefined
"C:/ti/tirtos_tivac_2_16_01_14/products/TivaWare_C_Series-2.1.1.71b/driverlib/emac.h", line 985: error #20: identifier "bool" is undefined

There must be another way of doing this. Can I change the MAC address through the NDK? Using the XGCONF tool? I notice that TIRTOS has many "wrapper" functions to access TIVAware drivers, and perhaps I need to use one of these instead of accessing this driver function directly.

Thank you!

  • Hi Noah,

      Can you add the below header file before #include <driverlib/emac.h> to resolve the error due to missing bool type definition. I tried it and I have no compilation error. 

    #include <stdbool.h>

  • Yes, now it compiles. However, the execution of the EMACAddrSet is causing an abort to be called. I'll do some more digging. Thank you!

  • What is the correct manner to use this function? I am calling EMACAddrSet before the FlashUserGet function, but when the first function is called, the program enters an infinite loop.

     *  ======== EK_TM4C129EXL_initEMAC ========
     */
    void EK_TM4C129EXL_initEMAC(void)
    {
        //NM
        static const uint8_t macArray[6] = {0xAC,0xDE,0x48,0x00,0x00,0x80};
        uint32_t ulUser0, ulUser1;
        //NM
        //EMACAddrSet(EMAC0_BASE,INT_EMAC0, macArray);


        /* Get the MAC address */
        FlashUserGet(&ulUser0, &ulUser1);
        if ((ulUser0 != 0xffffffff) && (ulUser1 != 0xffffffff)) {
            System_printf("Using MAC address in flash\n");
            /*
             *  Convert the 24/24 split MAC address from NV ram into a 32/16 split MAC
             *  address needed to program the hardware registers, then program the MAC
             *  address into the Ethernet Controller registers.
             */
            macAddress[0] = ((ulUser0 >>  0) & 0xff);
            macAddress[1] = ((ulUser0 >>  8) & 0xff);
            macAddress[2] = ((ulUser0 >> 16) & 0xff);
            macAddress[3] = ((ulUser1 >>  0) & 0xff);
            macAddress[4] = ((ulUser1 >>  8) & 0xff);
            macAddress[5] = ((ulUser1 >> 16) & 0xff);
        }
        else if (macAddress[0] == 0xff && macAddress[1] == 0xff &&
                 macAddress[2] == 0xff && macAddress[3] == 0xff &&
                 macAddress[4] == 0xff && macAddress[5] == 0xff) {
            System_abort("Change the macAddress variable to match your boards MAC sticker");
        }

        GPIOPinConfigure(GPIO_PF0_EN0LED0);  /* EK_TM4C129EXL_USR_D3 */
        GPIOPinConfigure(GPIO_PF4_EN0LED1);  /* EK_TM4C129EXL_USR_D4 */
        GPIOPinTypeEthernetLED(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4);


        /* Once EMAC_init is called, EMAC_config cannot be changed */
        EMAC_init();
    }

  • Hi Noeh,

      I think EMAC_init() will eventually call EMACSnow_NIMUInit() in C:\ti\tirtos_tivac_2_16_00_08\products\tidrivers_tivac_2_16_00_08\packages\ti\drivers\emac\EMACSnow.c file. In EMACSnow_NIMUInit() the macAddress array which comes from FlashUserGet will be programmed to the EMAC MAC address register using EMACAddrSet(). Therefore, if you call EMACAddrSet before EMAC_init, the MAC address is overwritten by the values that comes from FlashUserGet. 

      You can modify the EMACnow.c file by copying this file to the project directory at the same level as the EK_TM4C1294XL.c file. 

  • Charles,

    I have now tried several combinations and have encountered various errors. Before getting into the details, all I am looking to do is program a new MAC address into the TM4C129xxx MCU. If this can be done with UniFlash, LM Flash Programmer, or another tool, then this will solve my current hurdle. The problem with all of these tools, is that I must use an external Segger J-link device, not a Stellarius ICD. This is because I am using the Mikroe Fusion for TIVA 8 development system, which does not have an TI ICD available.

    Now, here's is what I've tried.

    Variation 1:

    1) I have copied EMACSnow.c/.h to my project's directory.

    2) I went through all of the workspace to ensure that these files were the ones being called, and in fact, I changed the names of the general drivers files by adding an underscore "_" to their names.

    3) I created a global bool flag that gets set if the MAC address is not found in Flash when the FlashUserGet function is called, and I created a global array that contains my desired MAC address.

    4) I commented out the call to  EMAC_init(); on line 336 of EK_TM4C129EXL.c.

    5) I inserted a call to EMAC_init(); within the EMACSnow_NIMUInit function just before the return statement at the end of the function (see below)

    Result: EMACSnow_NIMUInit is not called. Because of this the program enters into abort and loops forever.

    * ======== EMACSnow_NIMUInit ========
    * The function is used to initialize and register the EMACSnow
    * with the Network Interface Management Unit (NIMU)
    */
    int EMACSnow_NIMUInit(STKEVENT_Handle hEvent)
    {
    EMACSnow_HWAttrs *hwAttrs = (EMACSnow_HWAttrs *)(EMAC_config.hwAttrs);
    Types_FreqHz freq;
    NETIF_DEVICE *device;
    UInt32 ui32FlashConf;

    bool useDefaultMacAddr = useDefaultMac;

    Log_print0(Diags_USER2, "EMACSnow_NIMUInit: init called");

    /* Make sure application has initialized the EMAC driver first */
    Assert_isTrue((EMACSnow_initialized == TRUE), NULL);

    /* Initialize the global structures */
    memset(&EMACSnow_private, 0, sizeof(EMACSnow_Data));

    /*
    * This is a work-around for EMAC initialization issues found on
    * the TM4C129 devices. The bug number is:
    * SDOCM00107378: NDK examples for EK-TM4C1294XL do not work
    *
    * The following disables the flash pre-fetch (if it is not already disabled).
    * It is enable within the in the EMACSnow_emacStart() function.
    */
    ui32FlashConf = HWREG(FLASH_CONF);
    if ((ui32FlashConf & (FLASH_CONF_FPFOFF)) == FALSE) {
    enablePrefetch = TRUE;
    ui32FlashConf &= ~(FLASH_CONF_FPFON);
    ui32FlashConf |= FLASH_CONF_FPFOFF;
    HWREG(FLASH_CONF) = ui32FlashConf;
    }

    /* Allocate memory for the EMAC. Memory freed in the NDK stack shutdown */
    device = mmAlloc(sizeof(NETIF_DEVICE));
    if (device == NULL) {
    Log_error0("EMACSnow: Failed to allocate NETIF_DEVICE structure");
    return (-1);
    }

    /* Initialize the allocated memory block. */
    mmZeroInit (device, sizeof(NETIF_DEVICE));

    device->mac_address[0] = hwAttrs->macAddress[0];
    device->mac_address[1] = hwAttrs->macAddress[1];
    device->mac_address[2] = hwAttrs->macAddress[2];
    device->mac_address[3] = hwAttrs->macAddress[3];
    device->mac_address[4] = hwAttrs->macAddress[4];
    device->mac_address[5] = hwAttrs->macAddress[5];

    if (true == useDefaultMacAddr)
    {
    useDefaultMacAddr = false;

    device->mac_address[0] = defaultMacArray[0];
    device->mac_address[1] = defaultMacArray[1];
    device->mac_address[2] = defaultMacArray[2];
    device->mac_address[3] = defaultMacArray[3];
    device->mac_address[4] = defaultMacArray[4];
    device->mac_address[5] = defaultMacArray[5];
    }

    /* Initialize the Packet Device Information struct */
    PBMQ_init(&EMACSnow_private.PBMQ_rx);
    PBMQ_init(&EMACSnow_private.PBMQ_tx);
    EMACSnow_private.hEvent = hEvent;
    EMACSnow_private.pTxDescList = &g_TxDescList;
    EMACSnow_private.pRxDescList = &g_RxDescList;
    EMACSnow_private.rxCount = 0;
    EMACSnow_private.rxDropped = 0;
    EMACSnow_private.txSent = 0;
    EMACSnow_private.txDropped = 0;
    EMACSnow_private.abnormalInts = 0;
    EMACSnow_private.isrCount = 0;
    EMACSnow_private.linkUp = false;

    SysCtlPeripheralEnable(SYSCTL_PERIPH_EMAC0);
    SysCtlPeripheralReset(SYSCTL_PERIPH_EMAC0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_EPHY0);
    SysCtlPeripheralReset(SYSCTL_PERIPH_EPHY0);

    while (!SysCtlPeripheralReady(SYSCTL_PERIPH_EPHY0) ||
    !SysCtlPeripheralReady(SYSCTL_PERIPH_EMAC0)) {
    /* Keep waiting... */
    phyCounter[0]++;
    }

    EMACPHYConfigSet(EMAC0_BASE, EMAC_PHY_CONFIG);

    BIOS_getCpuFreq(&freq);
    EMACInit(EMAC0_BASE, freq.lo,
    EMAC_BCONFIG_MIXED_BURST | EMAC_BCONFIG_PRIORITY_FIXED,
    4, 4, 0);

    /* Set MAC configuration options. */
    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);

    /* Program the MAC address into the Ethernet controller. */
    EMACAddrSet(EMAC0_BASE, 0, (uint8_t *)device->mac_address);

    /* Initialize the DMA descriptors. */
    EMACSnow_InitDMADescriptors();

    /* Populate the Network Interface Object. */
    strcpy(device->name, ETHERNET_NAME);
    device->mtu = ETH_MAX_PAYLOAD - ETHHDR_SIZE;
    device->pvt_data = (void *)&EMACSnow_private;

    /* Populate the Driver Interface Functions. */
    device->start = EMACSnow_emacStart;
    device->stop = EMACSnow_emacStop;
    device->poll = EMACSnow_emacPoll;
    device->send = EMACSnow_emacSend;
    device->pkt_service = EMACSnow_pkt_service;
    device->ioctl = EMACSnow_emacioctl;
    device->add_header = NIMUAddEthernetHeader;

    /* Register the device with NIMU */
    if (NIMURegister(device) < 0) {
    Log_print0(Diags_USER1, "EMACSnow_NIMUInit: failed to register with NIMU");
    return (-1);
    }

    Log_print0(Diags_USER2, "EMACSnow_NIMUInit: register with NIMU");

    /* Once EMAC_init is called, EMAC_config cannot be changed */
    EMAC_init();

    return (0);
    }

    Variation 2:

    1) I have copied EMACSnow.c/.h to my project's directory.

    2) I went through all of the workspace to ensure that these files were the ones being called, and in fact, I changed the names of the general drivers files by adding an underscore "_" to their names.

    3) I created a global bool flag that gets set if the MAC address is not found in Flash when the FlashUserGet function is called, and I created a global array that contains my desired MAC address.

    4) I inserted a call to EMACSnow_NIMUInit  within the EK_TM4C129EXL_initEMAC just before EMAC_init(); is called. I passed NULL into the function.

    Result: EMACSnow_NIMUInit terminates at line 875 because the variable "device" is equal to NULL

    /* Allocate memory for the EMAC. Memory freed in the NDK stack shutdown */
    device = mmAlloc(sizeof(NETIF_DEVICE));
    if (device == NULL) {
    Log_error0("EMACSnow: Failed to allocate NETIF_DEVICE structure");
    return (-1);
    }

    void EK_TM4C129EXL_initEMAC(void)
    {
    //NM
    union ulUnion
    {
    uint64_t full;
    uint32_t halves[2];
    uint16_t quarters[4];
    uint8_t bytes[8];
    };
    //static const union ulUnion mac = {.full = DEFAULT_MAC_ADDR};


    uint32_t ulUser0, ulUser1, ui32FlashConf;
    //bool enablePrefetch = FALSE;
    uint32_t i = 0;
    //union ulUnion ulUser0, ulUser1;
    volatile uint32_t emacState = 0;
    //NM

    //emacState = EMACDMAStateGet(EMAC0_BASE);

    //EMACAddrSet(EMAC0_BASE,INT_EMAC0, macArray);

    //for (i = 0; i < 2; i++)
    {

    /* Get the MAC address */
    FlashUserGet(&ulUser0, &ulUser1);

    // if ((ulUser0 == 0xffffffff) && (ulUser1 == 0xffffffff))
    {
    /*
    * This is a work-around for EMAC initialization issues found on
    * the TM4C129 devices. The bug number is:
    * SDOCM00107378: NDK examples for EK-TM4C1294XL do not work
    *
    * The following disables the flash pre-fetch (if it is not already disabled).
    * It is enable within the in the EMACSnow_emacStart() function.
    */
    //ui32FlashConf = HWREG(FLASH_CONF);
    //if ((ui32FlashConf & (FLASH_CONF_FPFOFF)) == FALSE) {
    // enablePrefetch = TRUE;
    // ui32FlashConf &= ~(FLASH_CONF_FPFON);
    // ui32FlashConf |= FLASH_CONF_FPFOFF;
    // HWREG(FLASH_CONF) = ui32FlashConf;
    // }

    /* Program the MAC address into the Ethernet controller. */
    //EMACAddrSet(EMAC0_BASE, 0, (uint8_t *)macArray);
    }
    }


    //ulUser0 = mac.halves[1];

    //ulUser1 = mac.halves[0];


    if ((ulUser0 != 0xffffffff) && (ulUser1 != 0xffffffff)) {
    System_printf("Using MAC address in flash\n");
    /*
    * Convert the 24/24 split MAC address from NV ram into a 32/16 split MAC
    * address needed to program the hardware registers, then program the MAC
    * address into the Ethernet Controller registers.
    */
    macAddress[0] = ((ulUser0 >> 0) & 0xff);
    macAddress[1] = ((ulUser0 >> 8) & 0xff);
    macAddress[2] = ((ulUser0 >> 16) & 0xff);
    macAddress[3] = ((ulUser1 >> 0) & 0xff);
    macAddress[4] = ((ulUser1 >> 8) & 0xff);
    macAddress[5] = ((ulUser1 >> 16) & 0xff);
    }
    else if (macAddress[0] == 0xff && macAddress[1] == 0xff &&
    macAddress[2] == 0xff && macAddress[3] == 0xff &&
    macAddress[4] == 0xff && macAddress[5] == 0xff) {

    useDefaultMac = true;
    //System_abort("Change the macAddress variable to match your boards MAC sticker");
    }

    EMACSnow_NIMUInit(NULL);

    GPIOPinConfigure(GPIO_PF0_EN0LED0); /* EK_TM4C129EXL_USR_D3 */
    GPIOPinConfigure(GPIO_PF4_EN0LED1); /* EK_TM4C129EXL_USR_D4 */
    GPIOPinTypeEthernetLED(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4);


    /* Once EMAC_init is called, EMAC_config cannot be changed */
    EMAC_init();
    }

    Addition Support Request

    The advice provided makes sense, set up the MAC address and then call EMAC_init, but I do not understand where to insert this call, nor do I understand how to go about this. it seems that I need the ability to call, or to invoke a call to EMACSnow_NIMUInit in a thread safe manner. I am not sure how to ask this, but a more detailed example be provided? An example that shows where and how to implement the correct order or these functions so that a MAC address can be set in user flash programmatically. 

    Also, I can provide source code, the project, etc. I have not deviated very far from the provided tcpEcho example.

    Thank you!

  • Hi Noah,

      Looking through the callstack, it looks like EMACSnow_NIMUInit is called by NIMUInit from which comes from NC_NetStart. Therefore, EMACSnow_NIMUInit call does not come from EK_TM4C129EXL_initEMAC but rather called by the NDK stack. See below where I place a breakpoint inside EMACSnow_NIMUInit. I will suggest you:

    1) copy EMACSnow.c file to your project directory.

    2) Modify EMACSnow_NIMUInit so that it will use a new MAC address supplied by your application if there is not a MAC stored in the Flash USER0/USER1 registers.

    3) No need to modify EK_TM4C129EXL_initEMAC() in the EK_TM4C1294XL.c file. I tried putting a breakpoint on EMAC_init() in EK_TM4C129EXL_initEMAC() and also breakpoint in EMACSnow_NIMUInit. The EMAC_init() is halted before EMACSnow_NIMUInit. Therefore, adding a  call to EMACSnow_NIMUInit before EMAC_init() will be overwritten when the NDK stack calls EMACSnow_NIMUInit again. 

  • This worked! There remains one point that isn't working as I expected. It is my expectation that when the EMACAddrSet function is called, this would both set the immediate MAC address and write this value into the user flash - the same user flash that is read when using the FlashUserGet. The values read remain unchanged. Do I need to call the FlashUserSet function to update these values, and if this is the case, does this need to be performed after the call to EMACAddrSet , or can this be performed directly after the FlashUserGet call?

    The following information is for any other developer using the Mikroe Fusion for TIVA v8 development platform - no need for others to suffer. Slight smile

    Mikroe Hardware Changes

    • Change the dbg selection switch to external
    • In the "Board Setup" section, turn on the port LEDS for ports: A, B, and K.

    CCS Debug Configuration

    Apply the following configurations under "Target"

    CCS Target Configuration

    • Select SEGGER J-Link Emulator
    • Select Tiva TM4C129ENCPDT
    • Under the "Advanced" Tab, select SWD for the Target Interface

    Example Software Modifications

    • Modify the gpioPinConfigs[] array (EK_TM4C129ELX.c line 362) to the following:

    GPIO_PinConfig gpioPinConfigs[] =
    #ifdef MIKROE_DEV
    {
    /* Input pins */
    /* EK_TM4C129EXL_USR_SW1 */
    GPIOTiva_PA_0 | GPIO_CFG_IN_NOPULL | GPIO_CFG_IN_INT_NONE,
    /* EK_TM4C129EXL_USR_SW2 */
    GPIOTiva_PA_1 | GPIO_CFG_IN_NOPULL | GPIO_CFG_IN_INT_NONE,

    /* Output pins */
    /* EK_TM4C129EXL_USR_D1 */
    GPIOTiva_PB_0 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
    /* EK_TM4C129EXL_USR_D2 */
    GPIOTiva_PB_0 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
    };
    #else
    {
    /* Input pins */
    /* EK_TM4C129EXL_USR_SW1 */
    GPIOTiva_PJ_0 | GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_RISING,
    /* EK_TM4C129EXL_USR_SW2 */
    GPIOTiva_PJ_1 | GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_RISING,

    /* Output pins */
    /* EK_TM4C129EXL_USR_D1 */
    GPIOTiva_PN_1 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
    /* EK_TM4C129EXL_USR_D2 */
    GPIOTiva_PN_0 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
    };
    #endif

    • Modify the GPIO initialization functions as follows (EK_TM4C129ELX.c line 329):

    #ifdef MIKROE_DEV
    GPIOPinConfigure(GPIO_PK6_EN0LED1); /* EK_TM4C129EXL_USR_D3 */
    GPIOPinConfigure(GPIO_PK5_EN0LED2); /* EK_TM4C129EXL_USR_D4 */
    GPIOPinTypeEthernetLED(GPIO_PORTK_BASE, GPIO_PIN_5 | GPIO_PIN_6);
    #else
    GPIOPinConfigure(GPIO_PF0_EN0LED0); /* EK_TM4C129EXL_USR_D3 */
    GPIOPinConfigure(GPIO_PF4_EN0LED1); /* EK_TM4C129EXL_USR_D4 */
    GPIOPinTypeEthernetLED(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4);
    #endif

    /* Once EMAC_init is called, EMAC_config cannot be changed */
    EMAC_init();
    }

  • Do I need to call the FlashUserSet function to update these values, and if this is the case, does this need to be performed after the call to EMACAddrSet , or can this be performed directly after the FlashUserGet call?

    Yes, you can use FlashUserSet() to store a new MAC to the USER0/USER1 registers but bear in mind that these registers can only be wriiten once when the registers are in their erased state. Once a non-F's values is written to these registers you cannot write a new MAC value again. You must then perform a Unlock Operation to restore the device to its factory settings before you can write a new value. A virgin device will have USER0/USER1 register equal to all F's. You can program your new MAC before you call FlashUserGet() and by the time FlashUserGet() is called, it will return your newly stored value. However, if your MAC address is dynamically changing from one run to another then I guess you don't want to rely on FlashUserGet.