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: Combining the tcpEcho and uartEchoDma example projects into a single project - system abort being called and not sure why

Part Number: TM4C129ENCPDT

Tool/software:

Hello!

I am using this MCU to receive Ethernet-based commands, and then send out related, but different, UART data (this will eventually be an RS-485 bus with other embedded modules on this bus). To meet this end, I am combing the tcpEcho and uartEchoDma example projects together. I have gotten each of these to work individually.

The problem is when I have both sets of code included, the project will run for about 3 seconds, and the it jumps to abort. I have set the tcpTask to a priority of 1, and the uartTask to a priority of 2. No semaphores are being used, and I though this would be fine since the tcpTask seems to exit if there is not activity.

Do I need to coordinate between these two tasks using a semaphore, or event? The tcpTask should have the priority, but if there isn't any Ethernet activity, I want the uartTask to execute. I have provided my software files.

Thank you,

Noah

///////////////////////////////////////////////////////////////////////////////
/** @file "tcpEchoHooks.c"
*   @brief Contains tcp task and worker functions

-----------------------------------------------------------

@b Details

Contains the NDK hooks for TI RTOS.

@b Target
- TM4C129ENCPDT (CORTEX_M4_0
- ARM Compiler
- ARM Linker

@b Author(s)
- NIM(LASP)
- last revision by ($Author$)

Copyright © 2024, LASP

-----------------------------------------------------------

<b>Revision History:</b>
- 1.0:  10 Dec. 2024   Original
- last revision ($Date$)

-----------------------------------------------------------

<b>Attention</b>

// Includes
*/
/* XDCtools Header files */
#include <xdc/std.h>
#include <xdc/runtime/Error.h>
#include <xdc/runtime/System.h>

/* BIOS Header files */
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>

/* TCP Application Specific Header file. */
#include "tcp_sys.h"

// Constants

// Modular Variables

/* Prototypes */
Void tcpHandler(UArg arg0, UArg arg1);
// ============================================================================
// Private Functions
// ============================================================================

// ============================================================================
// Public Functions
// ============================================================================
//=============================================================================
/**
@return
- void

NDK network open hook used to initialize IPv6
*/
void netOpenHook()
{
    Task_Handle taskHandle;
    Task_Params taskParams;
    Error_Block eb;

    /* Make sure Error_Block is initialized */
    Error_init(&eb);

    /*
     *  Create the Task that farms out incoming TCP connections.
     *  arg0 will be the port that this task listens to.
     */
    Task_Params_init(&taskParams);
    taskParams.stackSize = TCPHANDLERSTACK;
    taskParams.priority = 1;
    taskParams.arg0 = TCPPORT;
    taskHandle = Task_create((Task_FuncPtr)tcpHandler, &taskParams, &eb);
    if (taskHandle == NULL) {
        System_printf("netOpenHook: Failed to create tcpHandler Task\n");
    }

    System_flush();
}

///////////////////////////////////////////////////////////////////////////////
/** @file "tcpEcho.c"
*   @brief Contains tcp task and worker functions

-----------------------------------------------------------

@b Details

Inherited from tcpEcho example. Contains task and worker
functions.

@b Target
- TM4C129ENCPDT (CORTEX_M4_0
- ARM Compiler
- ARM Linker

@b Author(s)
- NIM(LASP)
- last revision by ($Author$)

Copyright &copy; 2024, LASP

-----------------------------------------------------------

<b>Revision History:</b>
- 1.0:  10 Dec. 2024   Original
- last revision ($Date$)

-----------------------------------------------------------

<b>Attention</b>


*/
// Includes

#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>

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

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

/* TCP Application Specific Header file. */
#include "tcp_sys.h"
// Constants

// Modular Variables
// ============================================================================
// Private Functions
// ============================================================================
//=============================================================================
/**
@return
- void
Shuts down tcp task.
*/
static inline void	ShutDown
(
int32_t server	///< server index being referenced
)
//-----------------------------------------------------------------------------
{
    if (server > 0) 
	{
        close(server);
    }	
} //ShutDown
// ============================================================================
// Public Functions
// ============================================================================

//=============================================================================
/**
@return
- Void

 Task to handle TCP connection. Can be multiple Tasks running
 this function.
*/
Void tcpWorker
(
UArg arg0,	///< task argument 0 
UArg arg1	///< task argument 1
)
{
    int32_t  clientfd = (int32_t)arg0;
    int32_t  bytesRcvd;
    int32_t  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);
}
//=============================================================================
/**
@return
- Void
Creates new Task to handle new TCP connections.
*/
Void tcpHandler
(
UArg arg0,  ///< task argument 0
UArg arg1   ///< task argument 1
)
{
    int32_t                status;
    int32_t                clientfd;
    int32_t                server;
    struct sockaddr_in localAddr;
    struct sockaddr_in clientAddr;
    int32_t                optval;
    int32_t                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");
        ShutDown(server);//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");
        ShutDown(server);//goto shutdown;
    }

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

    optval = 1;
    if (setsockopt(server, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0) {
        System_printf("Error: setsockopt failed\n");
        ShutDown(server);//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;
        taskParams.priority = 1;
        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);
    //}
}

///////////////////////////////////////////////////////////////////////////////
/** @file "uartEcho.c"
*   @brief Contains uart task and worker functions

-----------------------------------------------------------

@b Details

Inherited from tcpEcho example. Contains task and worker
functions.

@b Target
- TM4C129ENCPDT (CORTEX_M4_0
- ARM Compiler
- ARM Linker

@b Author(s)
- NIM(LASP)
- last revision by ($Author$)

Copyright &copy; 2024, LASP

-----------------------------------------------------------

<b>Revision History:</b>
- 1.0:  11 Dec. 2024   Original
- last revision ($Date$)

-----------------------------------------------------------

<b>Attention</b>


*/
// Includes

#include <string.h>
#include <stdio.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>
#include <ti/drivers/UART.h>

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

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

/* TCP Application Specific Header file. */
#include "uart_sys.h"
// Constants

// Modular Variables
static UartSysType uartSys;
// ============================================================================
// Private Functions
// ============================================================================
//=============================================================================
/**
@return
- void

Clears modular variables.
*/
static void ClearModVars
(
	UartSysType* modVarPtr	///< modular variable pointer
)
{
	if (modVarPtr)
	{
		memset(modVarPtr, 0, sizeof(UartSysType));
	}
}
//=============================================================================
/**
@return
- int32_t: positive value means success; negative value means failure

Initializes uart parameters.
*/
static int32_t InitUartParams
(
        UART_Params* params
)
{
    int32_t returnVal = -1;

    if (params)
    {
        returnVal = 1;

        /* Create a UART with data processing off. */
        UART_Params_init(params);
        params->writeDataMode = UART_DATA_BINARY;
        params->readDataMode = UART_DATA_BINARY;
        params->readReturnMode = UART_RETURN_FULL;
        params->readEcho = UART_ECHO_OFF;
        params->baudRate = 9600;

    }

    return returnVal;
}
// ============================================================================
// Public Functions
// ============================================================================
//=============================================================================
/**
@return
- Void

 Task to handle TCP connection. Can be multiple Tasks running
 this function.
*/
Void echoFxn
(
UArg arg0,	///< TI RTOS argument 0
UArg arg1	///< TI RTOS argument 1
)
{


    UART_Params uartParams;
    const char echoPrompt[] = "\fEchoing characters:\r\n";

    InitUartParams(&uartParams);

#ifdef MIKROE_DEV
    UART_Handle uart2, uart4;
    uint32_t count = 0;
    uint32_t size = 0;
    uint32_t delay = 0;
    char outputString[16];
    char inputString[16];

    uart2 = UART_open(Board_UART2, &uartParams);
    if (uart2 == NULL) {
        System_abort("Error opening the UART");
    }

    InitUartParams(&uartParams);
    uart4 = UART_open(Board_UART4, &uartParams);
    if (uart4 == NULL) {
        System_abort("Error opening the UART");
    }

    UART_write(uart2, echoPrompt, sizeof(echoPrompt));

    /* Loop forever echoing */
    while (1)
    {
        //if(++delay >= 10000)
        {
            //delay = 0;

            //Task_sleep(1000);

            snprintf(outputString, 16, "Count is: %u",count);
            count++;
            size = strlen(outputString);
            UART_write(uart2, outputString, size);
            UART_read(uart4, inputString, 16);

            snprintf(outputString, 16, "%s",inputString);

            System_printf("The string sent was: %s\r\n", outputString);
            System_flush();
        }

    }
#else
    char input;
    UART_Handle uart0;

    uart0 = UART_open(Board_UART0, &uartParams);

    if (uart0 == NULL) {
        System_abort("Error opening the UART");
    }

    UART_write(uart0, echoPrompt, sizeof(echoPrompt));

    /* Loop forever echoing */
    while (1) {
        UART_read(uart0, &input, 1);
        UART_write(uart0, &input, 1);
    }
#endif





}
//=============================================================================
/**
@return
- void

Initializes the uart task.
*/
void initUartTask(void)
{
	ClearModVars(&uartSys);
	
    Task_Params_init(&uartSys.taskParams);
    uartSys.taskParams.stackSize = TASKSTACKSIZE;
    uartSys.taskParams.stack = &uartSys.task0Stack;
    uartSys.taskParams.instance->name = "echo";
    uartSys.taskParams.priority = 2;
    Task_construct(&uartSys.task0Struct, (Task_FuncPtr)echoFxn, &uartSys.taskParams, NULL);	
	
    /* This example has logging and many other debug capabilities enabled */
    System_printf("This example does not attempt to minimize code or data "
                  "footprint\n");
    System_flush();

    System_printf("Starting the UART 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();	
}
///////////////////////////////////////////////////////////////////////////////
/** @file "main.c"
*   @brief main module for AVTS Host MCU

-----------------------------------------------------------

@b Details

This project is built upon TI RTOS. From within this function,
initialization calls are made and the BIOS is started. 

@b Target
- TM4C129ENCPDT (CORTEX_M4_0
- ARM Compiler
- ARM Linker

@b Author(s)
- NIM(LASP)
- last revision by ($Author$)

Copyright &copy; 2024, LASP

-----------------------------------------------------------

<b>Revision History:</b>
- 1.0:  10 Dec. 2024   Original
- last revision ($Date$)

-----------------------------------------------------------

<b>Attention</b>


*/
///////////////////////////////////////////////////////////////////////////////

// Includes
#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>

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

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

/* AVTS Host MCU Specific Header files */
#include "uart_sys.h"

// Constants

// Modular Variables

// ============================================================================
// Private Functions
// ============================================================================

// ============================================================================
// Public Functions
// ============================================================================
//=============================================================================
/**
@return
- int32_t 

Main function and C starting point for the AVTS Host MCU software.

*/
int32_t main(void)
{
    //static const uint8_t macArray[6] = {0xAC,0xDE,0x48,0x00,0x00,0x80};
    /* Call board init functions */
    Board_initGeneral();
    Board_initGPIO();


    //NM
    //EMACAddrSet(EMAC0_BASE,INT_EMAC0, 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();

    Board_initUART();
    initUartTask();

    /* Start BIOS */
    BIOS_start();

    return (0);
}
/*
 * Copyright (c) 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.
 */

/*
 *  ======== EK_TM4C129EXL.c ========
 *  This file is responsible for setting up the board specific items for the
 *  EK_TM4C129EXL board.
 */

#include <stdint.h>
#include <stdbool.h>

#include <xdc/std.h>
#include <xdc/runtime/Error.h>
#include <xdc/runtime/System.h>
#include <ti/sysbios/family/arm/m3/Hwi.h>

#include <inc/hw_ints.h>
#include <inc/hw_memmap.h>
#include <inc/hw_types.h>
#include <inc/hw_gpio.h>

#include <driverlib/flash.h>
#include <driverlib/gpio.h>
#include <driverlib/i2c.h>
#include <driverlib/pin_map.h>
#include <driverlib/pwm.h>
#include <driverlib/ssi.h>
#include <driverlib/sysctl.h>
#include <driverlib/uart.h>
#include <driverlib/udma.h>

#include "EK_TM4C129EXL.h"

#define DEFAULT_MAC_ADDR 0xACDE48000080u

#include <inc/hw_flash.h>
#include <stdbool.h>

#ifndef TI_DRIVERS_UART_DMA
#define TI_DRIVERS_UART_DMA 0
#endif

#ifndef TI_EXAMPLES_PPP
#define TI_EXAMPLES_PPP 0
#else
/* prototype for NIMU init function */
extern int USBSerialPPP_NIMUInit();
#endif

/*
 *  =============================== DMA ===============================
 */
#if defined(__TI_COMPILER_VERSION__)
#pragma DATA_ALIGN(dmaControlTable, 1024)
#elif defined(__IAR_SYSTEMS_ICC__)
#pragma data_alignment=1024
#elif defined(__GNUC__)
__attribute__ ((aligned (1024)))
#endif
static tDMAControlTable dmaControlTable[32];
static bool dmaInitialized = false;

/* Hwi_Struct used in the initDMA Hwi_construct call */
static Hwi_Struct dmaHwiStruct;

/* Hwi_Struct used in the usbBusFault Hwi_construct call */
static Hwi_Struct usbBusFaultHwiStruct;

/*
 *  ======== dmaErrorHwi ========
 */
static Void dmaErrorHwi(UArg arg)
{
    System_printf("DMA error code: %d\n", uDMAErrorStatusGet());
    uDMAErrorStatusClear();
    System_abort("DMA error!!");
}

/*
 *  ======== EK_TM4C129EXL_usbBusFaultHwi ========
 */
static Void EK_TM4C129EXL_usbBusFaultHwi(UArg arg)
{
    /*
     *  This function should be modified to appropriately manage handle
     *  a USB bus fault.
    */
    System_printf("USB bus fault detected.");
    Hwi_clearInterrupt(INT_GPIOQ4);
    System_abort("USB error!!");
}

/*
 *  ======== EK_TM4C129EXL_initDMA ========
 */
void EK_TM4C129EXL_initDMA(void)
{
    Error_Block eb;
    Hwi_Params  hwiParams;

    if (!dmaInitialized) {
        Error_init(&eb);
        Hwi_Params_init(&hwiParams);
        Hwi_construct(&(dmaHwiStruct), INT_UDMAERR, dmaErrorHwi,
                      &hwiParams, &eb);
        if (Error_check(&eb)) {
            System_abort("Couldn't construct DMA error hwi");
        }

        SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
        uDMAEnable();
        uDMAControlBaseSet(dmaControlTable);

        dmaInitialized = true;
    }
}

/*
 *  =============================== General ===============================
 */
/*
 *  ======== EK_TM4C129EXL_initGeneral ========
 */
void EK_TM4C129EXL_initGeneral(void)
{
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOL);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOM);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOQ);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOR);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOS);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOT);
}

/*
 *  =============================== EMAC ===============================
 */
/* Place into subsections to allow the TI linker to remove items properly */
#if defined(__TI_COMPILER_VERSION__)
#pragma DATA_SECTION(EMAC_config, ".const:EMAC_config")
#pragma DATA_SECTION(emacHWAttrs, ".const:emacHWAttrs")
#pragma DATA_SECTION(NIMUDeviceTable, ".data:NIMUDeviceTable")
#endif

#include <ti/drivers/EMAC.h>
//#include <ti/drivers/emac/EMACSnow.h>

//NM
#include <stdbool.h>
#include <driverlib/emac.h>
#include "EMACSnow.h"

/*
 *  Required by the Networking Stack (NDK). This array must be NULL terminated.
 *  This can be removed if NDK is not used.
 *  Double curly braces are needed to avoid GCC bug #944572
 *  https://bugs.launchpad.net/gcc-linaro/+bug/944572
 */
NIMU_DEVICE_TABLE_ENTRY NIMUDeviceTable[2] = {
    {
#if TI_EXAMPLES_PPP
        /* Use PPP driver for PPP example only */
        .init = USBSerialPPP_NIMUInit
#else
        /* Default: use Ethernet driver */
        .init = EMACSnow_NIMUInit
#endif
    },
    {NULL}
};

EMACSnow_Object emacObjects[EK_TM4C129EXL_EMACCOUNT];

/*
 *  EMAC configuration structure
 *  Set user/company specific MAC octates. The following sets the address
 *  to ff-ff-ff-ff-ff-ff. Users need to change this to make the label on
 *  their boards.
 */
unsigned char macAddress[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};

const uint8_t defaultMacArray[6] = {0xAC,0xDE,0x48,0x00,0x00,0x80};
bool useDefaultMac = false;

const EMACSnow_HWAttrs emacHWAttrs[EK_TM4C129EXL_EMACCOUNT] = {
    {
        .baseAddr = EMAC0_BASE,
        .intNum = INT_EMAC0,
        .intPriority = (~0),
        .macAddress = macAddress
    }
};

const EMAC_Config EMAC_config[] = {
    {
        .fxnTablePtr = &EMACSnow_fxnTable,
        .object = &emacObjects[0],
        .hwAttrs = &emacHWAttrs[0]
    },
    {NULL, NULL, NULL}
};

/*
 *  ======== EK_TM4C129EXL_initEMAC ========
 */
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);
#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();
}

/*
 *  =============================== GPIO ===============================
 */
/* Place into subsections to allow the TI linker to remove items properly */
#if defined(__TI_COMPILER_VERSION__)
#pragma DATA_SECTION(GPIOTiva_config, ".const:GPIOTiva_config")
#endif

#include <ti/drivers/GPIO.h>
#include <ti/drivers/gpio/GPIOTiva.h>

/*
 * Array of Pin configurations
 * NOTE: The order of the pin configurations must coincide with what was
 *       defined in EK_TM4C129EXL.h
 * NOTE: Pins not used for interrupts should be placed at the end of the
 *       array.  Callback entries can be omitted from callbacks array to
 *       reduce memory usage.
 */
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
/*
 * Array of callback function pointers
 * NOTE: The order of the pin configurations must coincide with what was
 *       defined in EK_TM4C129EXL.h
 * NOTE: Pins not used for interrupts can be omitted from callbacks array to
 *       reduce memory usage (if placed at end of gpioPinConfigs array).
 */
GPIO_CallbackFxn gpioCallbackFunctions[] = {
    NULL,  /* EK_TM4C129EXL_USR_SW1 */
    NULL   /* EK_TM4C129EXL_USR_SW2 */
};

/* The device-specific GPIO_config structure */
const GPIOTiva_Config GPIOTiva_config = {
    .pinConfigs = (GPIO_PinConfig *)gpioPinConfigs,
    .callbacks = (GPIO_CallbackFxn *)gpioCallbackFunctions,
    .numberOfPinConfigs = sizeof(gpioPinConfigs)/sizeof(GPIO_PinConfig),
    .numberOfCallbacks = sizeof(gpioCallbackFunctions)/sizeof(GPIO_CallbackFxn),
    .intPriority = (~0)
};

/*
 *  ======== EK_TM4C129EXL_initGPIO ========
 */
void EK_TM4C129EXL_initGPIO(void)
{
    /* Initialize peripheral and pins */
    GPIO_init();
}

/*
 *  =============================== I2C ===============================
 */
/* Place into subsections to allow the TI linker to remove items properly */
#if defined(__TI_COMPILER_VERSION__)
#pragma DATA_SECTION(I2C_config, ".const:I2C_config")
#pragma DATA_SECTION(i2cTivaHWAttrs, ".const:i2cTivaHWAttrs")
#endif

#include <ti/drivers/I2C.h>
#include <ti/drivers/i2c/I2CTiva.h>

I2CTiva_Object i2cTivaObjects[EK_TM4C129EXL_I2CCOUNT];

const I2CTiva_HWAttrs i2cTivaHWAttrs[EK_TM4C129EXL_I2CCOUNT] = {
    {
        .baseAddr = I2C7_BASE,
        .intNum = INT_I2C7,
        .intPriority = (~0)
    },
    {
        .baseAddr = I2C8_BASE,
        .intNum = INT_I2C8,
        .intPriority = (~0)
    },
};

const I2C_Config I2C_config[] = {
    {
        .fxnTablePtr = &I2CTiva_fxnTable,
        .object = &i2cTivaObjects[0],
        .hwAttrs = &i2cTivaHWAttrs[0]
    },
    {
        .fxnTablePtr = &I2CTiva_fxnTable,
        .object = &i2cTivaObjects[1],
        .hwAttrs = &i2cTivaHWAttrs[1]
    },
    {NULL, NULL, NULL}
};

/*
 *  ======== EK_TM4C129EXL_initI2C ========
 */
void EK_TM4C129EXL_initI2C(void)
{
    /* I2C7 Init */
    /*
     * NOTE: TI-RTOS examples configure pins PD0 & PD1 for SSI2 or I2C7.  Thus,
     * a conflict occurs when the I2C & SPI drivers are used simultaneously in
     * an application.  Modify the pin mux settings in this file and resolve the
     * conflict before running your the application.
     */
    /* Enable the peripheral */
    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C7);

    /* Configure the appropriate pins to be I2C instead of GPIO. */
    GPIOPinConfigure(GPIO_PD0_I2C7SCL);
    GPIOPinConfigure(GPIO_PD1_I2C7SDA);
    GPIOPinTypeI2CSCL(GPIO_PORTD_BASE, GPIO_PIN_0);
    GPIOPinTypeI2C(GPIO_PORTD_BASE, GPIO_PIN_1);

    /* I2C8 Init */
    /* Enable the peripheral */
    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C8);

    /* Configure the appropriate pins to be I2C instead of GPIO. */
    GPIOPinConfigure(GPIO_PA2_I2C8SCL);
    GPIOPinConfigure(GPIO_PA3_I2C8SDA);
    GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_2);
    GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_3);

    I2C_init();
}

/*
 *  =============================== PWM ===============================
 */
/* Place into subsections to allow the TI linker to remove items properly */
#if defined(__TI_COMPILER_VERSION__)
#pragma DATA_SECTION(PWM_config, ".const:PWM_config")
#pragma DATA_SECTION(pwmTivaHWAttrs, ".const:pwmTivaHWAttrs")
#endif

#include <ti/drivers/PWM.h>
#include <ti/drivers/pwm/PWMTiva.h>

PWMTiva_Object pwmTivaObjects[EK_TM4C129EXL_PWMCOUNT];

const PWMTiva_HWAttrs pwmTivaHWAttrs[EK_TM4C129EXL_PWMCOUNT] = {
    {
        .baseAddr = PWM0_BASE,
        .pwmOutput = PWM_OUT_0,
        .pwmGenOpts = PWM_GEN_MODE_DOWN | PWM_GEN_MODE_DBG_RUN
    }
};

const PWM_Config PWM_config[] = {
    {
        .fxnTablePtr = &PWMTiva_fxnTable,
        .object = &pwmTivaObjects[0],
        .hwAttrs = &pwmTivaHWAttrs[0]
    },
    {NULL, NULL, NULL}
};

/*
 *  ======== EK_TM4C129EXL_initPWM ========
 */
void EK_TM4C129EXL_initPWM(void)
{
    /* Enable PWM peripherals */
    SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);

    /*
     * Enable PWM output on GPIO pins.  PWM output is connected to an Ethernet
     * LED on the development board (D4).  The PWM configuration
     * below will disable Ethernet functionality.
     */
    GPIOPinConfigure(GPIO_PF0_M0PWM0);
    GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_0);

    PWM_init();
}

/*
 *  =============================== SDSPI ===============================
 */
/* Place into subsections to allow the TI linker to remove items properly */
#if defined(__TI_COMPILER_VERSION__)
#pragma DATA_SECTION(SDSPI_config, ".const:SDSPI_config")
#pragma DATA_SECTION(sdspiTivaHWattrs, ".const:sdspiTivaHWattrs")
#endif

#include <ti/drivers/SDSPI.h>
#include <ti/drivers/sdspi/SDSPITiva.h>

SDSPITiva_Object sdspiTivaObjects[EK_TM4C129EXL_SDSPICOUNT];

const SDSPITiva_HWAttrs sdspiTivaHWattrs[EK_TM4C129EXL_SDSPICOUNT] = {
    {
        .baseAddr = SSI2_BASE,

        .portSCK = GPIO_PORTD_BASE,
        .pinSCK = GPIO_PIN_3,
        .portMISO = GPIO_PORTD_BASE,
        .pinMISO = GPIO_PIN_0,
        .portMOSI = GPIO_PORTD_BASE,
        .pinMOSI = GPIO_PIN_1,
        .portCS = GPIO_PORTC_BASE,
        .pinCS = GPIO_PIN_7,
    },
    {
        .baseAddr = SSI3_BASE,

        .portSCK = GPIO_PORTQ_BASE,
        .pinSCK = GPIO_PIN_0,
        .portMISO = GPIO_PORTQ_BASE,
        .pinMISO = GPIO_PIN_3,
        .portMOSI = GPIO_PORTQ_BASE,
        .pinMOSI = GPIO_PIN_2,
        .portCS = GPIO_PORTP_BASE,
        .pinCS = GPIO_PIN_4,
    }
};

const SDSPI_Config SDSPI_config[] = {
    {
        .fxnTablePtr = &SDSPITiva_fxnTable,
        .object = &sdspiTivaObjects[0],
        .hwAttrs = &sdspiTivaHWattrs[0]
    },
    {
        .fxnTablePtr = &SDSPITiva_fxnTable,
        .object = &sdspiTivaObjects[1],
        .hwAttrs = &sdspiTivaHWattrs[1]
    },
    {NULL, NULL, NULL}
};

/*
 *  ======== EK_TM4C129EXL_initSDSPI ========
 */
void EK_TM4C129EXL_initSDSPI(void)
{
    /* SDSPI0 configuration */
    /* Enable the peripherals used by the SD Card */
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2);

    /* Configure pad settings */
    GPIOPadConfigSet(GPIO_PORTD_BASE,
                     GPIO_PIN_3 | GPIO_PIN_1,
                     GPIO_STRENGTH_4MA, GPIO_PIN_TYPE_STD);

    GPIOPadConfigSet(GPIO_PORTD_BASE,
                     GPIO_PIN_0,
                     GPIO_STRENGTH_4MA, GPIO_PIN_TYPE_STD_WPU);

    GPIOPadConfigSet(GPIO_PORTC_BASE,
                     GPIO_PIN_7,
                     GPIO_STRENGTH_4MA, GPIO_PIN_TYPE_STD);

    GPIOPinConfigure(GPIO_PD3_SSI2CLK);
    GPIOPinConfigure(GPIO_PD0_SSI2XDAT1);
    GPIOPinConfigure(GPIO_PD1_SSI2XDAT0);

    /* SDSPI1 configuration */
    /* Enable the peripherals used by the SD Card */
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI3);

    /* Configure pad settings */
    GPIOPadConfigSet(GPIO_PORTQ_BASE,
                     GPIO_PIN_0 | GPIO_PIN_2,
                     GPIO_STRENGTH_4MA, GPIO_PIN_TYPE_STD);

    GPIOPadConfigSet(GPIO_PORTQ_BASE,
                     GPIO_PIN_3,
                     GPIO_STRENGTH_4MA, GPIO_PIN_TYPE_STD_WPU);

    GPIOPadConfigSet(GPIO_PORTP_BASE,
                     GPIO_PIN_4,
                     GPIO_STRENGTH_4MA, GPIO_PIN_TYPE_STD);

    GPIOPinConfigure(GPIO_PQ0_SSI3CLK);
    GPIOPinConfigure(GPIO_PQ3_SSI3XDAT1);
    GPIOPinConfigure(GPIO_PQ2_SSI3XDAT0);

    /*
     *  These GPIOs are connected to PA2 and PA3 and need to be brought into a
     *  GPIO input state so they don't interfere with SPI communications.
     */
    GPIOPinTypeGPIOInput(GPIO_PORTA_BASE, GPIO_PIN_2);
    GPIOPinTypeGPIOInput(GPIO_PORTA_BASE, GPIO_PIN_3);

    SDSPI_init();
}

/*
 *  =============================== SPI ===============================
 */
/* Place into subsections to allow the TI linker to remove items properly */
#if defined(__TI_COMPILER_VERSION__)
#pragma DATA_SECTION(SPI_config, ".const:SPI_config")
#pragma DATA_SECTION(spiTivaDMAHWAttrs, ".const:spiTivaDMAHWAttrs")
#endif

#include <ti/drivers/SPI.h>
#include <ti/drivers/spi/SPITivaDMA.h>

SPITivaDMA_Object spiTivaDMAObjects[EK_TM4C129EXL_SPICOUNT];

#if defined(__TI_COMPILER_VERSION__)
#pragma DATA_ALIGN(spiTivaDMAscratchBuf, 32)
#elif defined(__IAR_SYSTEMS_ICC__)
#pragma data_alignment=32
#elif defined(__GNUC__)
__attribute__ ((aligned (32)))
#endif
uint32_t spiTivaDMAscratchBuf[EK_TM4C129EXL_SPICOUNT];

const SPITivaDMA_HWAttrs spiTivaDMAHWAttrs[EK_TM4C129EXL_SPICOUNT] = {
    {
        .baseAddr = SSI2_BASE,
        .intNum = INT_SSI2,
        .intPriority = (~0),
        .scratchBufPtr = &spiTivaDMAscratchBuf[0],
        .defaultTxBufValue = 0,
        .rxChannelIndex = UDMA_SEC_CHANNEL_UART2RX_12,
        .txChannelIndex = UDMA_SEC_CHANNEL_UART2TX_13,
        .channelMappingFxn = uDMAChannelAssign,
        .rxChannelMappingFxnArg = UDMA_CH12_SSI2RX,
        .txChannelMappingFxnArg = UDMA_CH13_SSI2TX
    },
    {
        .baseAddr = SSI3_BASE,
        .intNum = INT_SSI3,
        .intPriority = (~0),
        .scratchBufPtr = &spiTivaDMAscratchBuf[1],
        .defaultTxBufValue = 0,
        .rxChannelIndex = UDMA_SEC_CHANNEL_TMR2A_14,
        .txChannelIndex = UDMA_SEC_CHANNEL_TMR2B_15,
        .channelMappingFxn = uDMAChannelAssign,
        .rxChannelMappingFxnArg = UDMA_CH14_SSI3RX,
        .txChannelMappingFxnArg = UDMA_CH15_SSI3TX
    }
};

const SPI_Config SPI_config[] = {
    {
        .fxnTablePtr = &SPITivaDMA_fxnTable,
        .object = &spiTivaDMAObjects[0],
        .hwAttrs = &spiTivaDMAHWAttrs[0]
    },
    {
        .fxnTablePtr = &SPITivaDMA_fxnTable,
        .object = &spiTivaDMAObjects[1],
        .hwAttrs = &spiTivaDMAHWAttrs[1]
    },
    {NULL, NULL, NULL}
};

/*
 *  ======== EK_TM4C129EXL_initSPI ========
 */
void EK_TM4C129EXL_initSPI(void)
{
    /* SSI2 */
    /*
     * NOTE: TI-RTOS examples configure pins PD0 & PD1 for SSI2 or I2C7.  Thus,
     * a conflict occurs when the I2C & SPI drivers are used simultaneously in
     * an application.  Modify the pin mux settings in this file and resolve the
     * conflict before running your the application.
     */
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2);

    GPIOPinConfigure(GPIO_PD3_SSI2CLK);
    GPIOPinConfigure(GPIO_PD2_SSI2FSS);
    GPIOPinConfigure(GPIO_PD1_SSI2XDAT0);
    GPIOPinConfigure(GPIO_PD0_SSI2XDAT1);

    GPIOPinTypeSSI(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1 |
                                    GPIO_PIN_2 | GPIO_PIN_3);

    /* SSI3 */
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI3);

    GPIOPinConfigure(GPIO_PQ0_SSI3CLK);
    GPIOPinConfigure(GPIO_PQ1_SSI3FSS);
    GPIOPinConfigure(GPIO_PQ2_SSI3XDAT0);
    GPIOPinConfigure(GPIO_PQ3_SSI3XDAT1);

    GPIOPinTypeSSI(GPIO_PORTQ_BASE, GPIO_PIN_0 | GPIO_PIN_1 |
                                    GPIO_PIN_2 | GPIO_PIN_3);

    EK_TM4C129EXL_initDMA();
    SPI_init();
}

/*
 *  =============================== UART ===============================
 */
/* Place into subsections to allow the TI linker to remove items properly */
#if defined(__TI_COMPILER_VERSION__)
#pragma DATA_SECTION(UART_config, ".const:UART_config")
#pragma DATA_SECTION(uartTivaHWAttrs, ".const:uartTivaHWAttrs")
#endif

#include <ti/drivers/UART.h>
#if TI_DRIVERS_UART_DMA
#include <ti/drivers/uart/UARTTivaDMA.h>

UARTTivaDMA_Object uartTivaObjects[EK_TM4C129EXL_UARTCOUNT];

const UARTTivaDMA_HWAttrs uartTivaHWAttrs[EK_TM4C129EXL_UARTCOUNT] = {
    {
        .baseAddr = UART0_BASE,
        .intNum = INT_UART0,
        .intPriority = (~0),
        .rxChannelIndex = UDMA_CH8_UART0RX,
        .txChannelIndex = UDMA_CH9_UART0TX,
    }
#ifdef MIKROE_DEV
    ,
    {
        .baseAddr = UART1_BASE,
        .intNum = INT_UART1,
        .intPriority = (~0),
        .rxChannelIndex = UDMA_CH8_UART1RX,
        .txChannelIndex = UDMA_CH9_UART1TX,
    },
    {
        .baseAddr = UART2_BASE,
        .intNum = INT_UART2,
        .intPriority = (~0),
        .rxChannelIndex = UDMA_CH12_UART2RX,
        .txChannelIndex = UDMA_CH13_UART2TX,
    },
    {
        .baseAddr = UART3_BASE,
        .intNum = INT_UART3,
        .intPriority = (~0),
        .rxChannelIndex = UDMA_CH16_UART3RX,
        .txChannelIndex = UDMA_CH17_UART3TX,
    },
    {
        .baseAddr = UART4_BASE,
        .intNum = INT_UART4,
        .intPriority = (~0),
        .rxChannelIndex = UDMA_CH18_UART4RX,
        .txChannelIndex = UDMA_CH19_UART4TX,
    }
#endif
};

const UART_Config UART_config[] = {
    {
        .fxnTablePtr = &UARTTivaDMA_fxnTable,
        .object = &uartTivaObjects[0],
        .hwAttrs = &uartTivaHWAttrs[0]
    },
#ifdef MIKROE_DEV
    {
        .fxnTablePtr = &UARTTivaDMA_fxnTable,
        .object = &uartTivaObjects[1],
        .hwAttrs = &uartTivaHWAttrs[1]
    },
    {
        .fxnTablePtr = &UARTTivaDMA_fxnTable,
        .object = &uartTivaObjects[2],
        .hwAttrs = &uartTivaHWAttrs[2]
    },
    {
        .fxnTablePtr = &UARTTivaDMA_fxnTable,
        .object = &uartTivaObjects[3],
        .hwAttrs = &uartTivaHWAttrs[3]
    },
    {
        .fxnTablePtr = &UARTTivaDMA_fxnTable,
        .object = &uartTivaObjects[4],
        .hwAttrs = &uartTivaHWAttrs[4]
    },
#endif
    {NULL, NULL, NULL}



};
#else
#include <ti/drivers/uart/UARTTiva.h>

UARTTiva_Object uartTivaObjects[EK_TM4C129EXL_UARTCOUNT];
unsigned char uartTivaRingBuffer[EK_TM4C129EXL_UARTCOUNT][32];

/* UART configuration structure */
const UARTTiva_HWAttrs uartTivaHWAttrs[EK_TM4C129EXL_UARTCOUNT] =
{
    {
        .baseAddr = UART0_BASE,
        .intNum = INT_UART0,
        .intPriority = (~0),
        .flowControl = UART_FLOWCONTROL_NONE,
        .ringBufPtr  = uartTivaRingBuffer[0],
        .ringBufSize = sizeof(uartTivaRingBuffer[0])
    }
#ifdef MIKROE_DEV
    ,
    {
        .baseAddr = UART1_BASE,
        .intNum = INT_UART1,
        .intPriority = (~0),
        .flowControl = UART_FLOWCONTROL_NONE,
        .ringBufPtr  = uartTivaRingBuffer[1],
        .ringBufSize = sizeof(uartTivaRingBuffer[1])
    },
    {
        .baseAddr = UART2_BASE,
        .intNum = INT_UART2,
        .intPriority = (~0),
        .flowControl = UART_FLOWCONTROL_NONE,
        .ringBufPtr  = uartTivaRingBuffer[2],
        .ringBufSize = sizeof(uartTivaRingBuffer[2])
    },
    {
        .baseAddr = UART3_BASE,
        .intNum = INT_UART3,
        .intPriority = (~0),
        .flowControl = UART_FLOWCONTROL_NONE,
        .ringBufPtr  = uartTivaRingBuffer[3],
        .ringBufSize = sizeof(uartTivaRingBuffer[3])
    },
    {
        .baseAddr = UART4_BASE,
        .intNum = INT_UART4,
        .intPriority = (~0),
        .flowControl = UART_FLOWCONTROL_NONE,
        .ringBufPtr  = uartTivaRingBuffer[4],
        .ringBufSize = sizeof(uartTivaRingBuffer[4])
    }
#endif
};

const UART_Config UART_config[EK_TM4C129EXL_UARTCOUNT] = {
    {
        .fxnTablePtr = &UARTTiva_fxnTable,
        .object = &uartTivaObjects[0],
        .hwAttrs = &uartTivaHWAttrs[0]
    }
#ifndef MIKROE_DEV
    ,
    {NULL, NULL, NULL}
#else
    ,
    {
        .fxnTablePtr = &UARTTiva_fxnTable,
        .object = &uartTivaObjects[1],
        .hwAttrs = &uartTivaHWAttrs[1]
    },
    {
        .fxnTablePtr = &UARTTiva_fxnTable,
        .object = &uartTivaObjects[2],
        .hwAttrs = &uartTivaHWAttrs[2]
    },
    {
        .fxnTablePtr = &UARTTiva_fxnTable,
        .object = &uartTivaObjects[3],
        .hwAttrs = &uartTivaHWAttrs[3]
    },
    {
        .fxnTablePtr = &UARTTiva_fxnTable,
        .object = &uartTivaObjects[4],
        .hwAttrs = &uartTivaHWAttrs[4]
    }
#endif
};
#endif /* TI_DRIVERS_UART_DMA */

/*
 *  ======== EK_TM4C129EXL_initUART ========
 */
void EK_TM4C129EXL_initUART(void)
{
#ifdef MIKROE_DEV
    /* Using the mikroBUs 1 port */
    /* Enable and configure the peripherals used by the uart. */
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART4);
    GPIOPinConfigure(GPIO_PK0_U4RX);
    GPIOPinConfigure(GPIO_PK1_U4TX);
    GPIOPinTypeUART(GPIO_PORTK_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    /* Using the mikroBUs 5 port */
    /* Enable and configure the peripherals used by the uart. */
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART2);
    GPIOPinConfigure(GPIO_PD4_U2RX);
    GPIOPinConfigure(GPIO_PD5_U2TX);
    GPIOPinTypeUART(GPIO_PORTD_BASE, GPIO_PIN_4 | GPIO_PIN_5);

#else

    /* Enable and configure the peripherals used by the uart. */
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
#endif
    /* Initialize the UART driver */
#if TI_DRIVERS_UART_DMA
    EK_TM4C129EXL_initDMA();
#endif
    UART_init();
}

/*
 *  =============================== USB ===============================
 */
/*
 *  ======== EK_TM4C129EXL_initUSB ========
 *  This function just turns on the USB
 */
void EK_TM4C129EXL_initUSB(EK_TM4C129EXL_USBMode usbMode)
{
    Error_Block eb;
    Hwi_Params  hwiParams;

    /* Enable the USB peripheral and PLL */
    SysCtlPeripheralEnable(SYSCTL_PERIPH_USB0);
    SysCtlUSBPLLEnable();

    /* Setup pins for USB operation */
    GPIOPinTypeUSBAnalog(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    GPIOPinTypeUSBAnalog(GPIO_PORTL_BASE, GPIO_PIN_6 | GPIO_PIN_7);

    /* Additional configurations for Host mode */
    if (usbMode == EK_TM4C129EXL_USBHOST) {
        /* Configure the pins needed */
        HWREG(GPIO_PORTD_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
        HWREG(GPIO_PORTD_BASE + GPIO_O_CR) = 0xff;
        GPIOPinConfigure(GPIO_PD6_USB0EPEN);
        GPIOPinTypeUSBDigital(GPIO_PORTD_BASE, GPIO_PIN_6 | GPIO_PIN_7);

        /*
         *  USB bus fault is routed to pin PQ4.  We create a Hwi to allow us
         *  to detect power faults and recover gracefully or terminate the
         *  program.  PQ4 is active low; set the pin as input with a weak
         *  pull-up.
         */
        GPIOPadConfigSet(GPIO_PORTQ_BASE, GPIO_PIN_4,
                         GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
        GPIOIntTypeSet(GPIO_PORTQ_BASE, GPIO_PIN_4, GPIO_FALLING_EDGE);
        GPIOIntClear(GPIO_PORTQ_BASE, GPIO_PIN_4);

        /* Create a Hwi for PQ4 pin. */
        Error_init(&eb);
        Hwi_Params_init(&hwiParams);
        Hwi_construct(&(usbBusFaultHwiStruct), INT_GPIOQ4,
                      EK_TM4C129EXL_usbBusFaultHwi, &hwiParams, &eb);
        if (Error_check(&eb)) {
            System_abort("Couldn't construct USB bus fault hwi");
        }
    }
}

/*
 *  =============================== USBMSCHFatFs ===============================
 */
/* Place into subsections to allow the TI linker to remove items properly */
#if defined(__TI_COMPILER_VERSION__)
#pragma DATA_SECTION(USBMSCHFatFs_config, ".const:USBMSCHFatFs_config")
#pragma DATA_SECTION(usbmschfatfstivaHWAttrs, ".const:usbmschfatfstivaHWAttrs")
#endif

#include <ti/drivers/USBMSCHFatFs.h>
#include <ti/drivers/usbmschfatfs/USBMSCHFatFsTiva.h>

USBMSCHFatFsTiva_Object usbmschfatfstivaObjects[EK_TM4C129EXL_USBMSCHFatFsCOUNT];

const USBMSCHFatFsTiva_HWAttrs usbmschfatfstivaHWAttrs[EK_TM4C129EXL_USBMSCHFatFsCOUNT] = {
    {
        .intNum = INT_USB0,
        .intPriority = (~0)
    }
};

const USBMSCHFatFs_Config USBMSCHFatFs_config[] = {
    {
        .fxnTablePtr = &USBMSCHFatFsTiva_fxnTable,
        .object = &usbmschfatfstivaObjects[0],
        .hwAttrs = &usbmschfatfstivaHWAttrs[0]
    },
    {NULL, NULL, NULL}
};

/*
 *  ======== EK_TM4C129EXL_initUSBMSCHFatFs ========
 */
void EK_TM4C129EXL_initUSBMSCHFatFs(void)
{
    /* Initialize the DMA control table */
    EK_TM4C129EXL_initDMA();

    /* Call the USB initialization function for the USB Reference modules */
    EK_TM4C129EXL_initUSB(EK_TM4C129EXL_USBHOST);
    USBMSCHFatFs_init();
}

/*
 *  =============================== Watchdog ===============================
 */
/* Place into subsections to allow the TI linker to remove items properly */
#if defined(__TI_COMPILER_VERSION__)
#pragma DATA_SECTION(Watchdog_config, ".const:Watchdog_config")
#pragma DATA_SECTION(watchdogTivaHWAttrs, ".const:watchdogTivaHWAttrs")
#endif

#include <ti/drivers/Watchdog.h>
#include <ti/drivers/watchdog/WatchdogTiva.h>

WatchdogTiva_Object watchdogTivaObjects[EK_TM4C129EXL_WATCHDOGCOUNT];

const WatchdogTiva_HWAttrs watchdogTivaHWAttrs[EK_TM4C129EXL_WATCHDOGCOUNT] = {
    {
        .baseAddr = WATCHDOG0_BASE,
        .intNum = INT_WATCHDOG,
        .intPriority = (~0),
        .reloadValue = 80000000 // 1 second period at default CPU clock freq
    },
};

const Watchdog_Config Watchdog_config[] = {
    {
        .fxnTablePtr = &WatchdogTiva_fxnTable,
        .object = &watchdogTivaObjects[0],
        .hwAttrs = &watchdogTivaHWAttrs[0]
    },
    {NULL, NULL, NULL},
};

/*
 *  ======== EK_TM4C129EXL_initWatchdog ========
 *
 * NOTE: To use the other watchdog timer with base address WATCHDOG1_BASE,
 *       an additional function call may need be made to enable PIOSC. Enabling
 *       WDOG1 does not do this. Enabling another peripheral that uses PIOSC
 *       such as ADC0 or SSI0, however, will do so. Example:
 *
 *       SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
 *       SysCtlPeripheralEnable(SYSCTL_PERIPH_WDOG1);
 *
 *       See the following forum post for more information:
 *       http://e2e.ti.com/support/microcontrollers/stellaris_arm_cortex-m3_microcontroller/f/471/p/176487/654390.aspx#654390
 */
void EK_TM4C129EXL_initWatchdog(void)
{
    /* Enable peripherals used by Watchdog */
    SysCtlPeripheralEnable(SYSCTL_PERIPH_WDOG0);

    Watchdog_init();
}

/*
 *  =============================== WiFi ===============================
 */
/* Place into subsections to allow the TI linker to remove items properly */
#if defined(__TI_COMPILER_VERSION__)
#pragma DATA_SECTION(WiFi_config, ".const:WiFi_config")
#pragma DATA_SECTION(wiFiCC3100HWAttrs, ".const:wiFiCC3100HWAttrs")
#endif

#include <ti/drivers/WiFi.h>
#include <ti/drivers/wifi/WiFiCC3100.h>

WiFiCC3100_Object wiFiCC3100Objects[EK_TM4C129EXL_WIFICOUNT];

const WiFiCC3100_HWAttrs wiFiCC3100HWAttrs[EK_TM4C129EXL_WIFICOUNT] = {
    {
        .irqPort = GPIO_PORTM_BASE,
        .irqPin = GPIO_PIN_3,
        .irqIntNum = INT_GPIOM,

        .csPort = GPIO_PORTH_BASE,
        .csPin = GPIO_PIN_2,

        .enPort = GPIO_PORTC_BASE,
        .enPin = GPIO_PIN_6
    }
};

const WiFi_Config WiFi_config[] = {
    {
        .fxnTablePtr = &WiFiCC3100_fxnTable,
        .object = &wiFiCC3100Objects[0],
        .hwAttrs = &wiFiCC3100HWAttrs[0]
    },
    {NULL,NULL, NULL},
};

/*
 *  ======== EK_TM4C129EXL_initWiFi ========
 */
void EK_TM4C129EXL_initWiFi(void)
{
    /* Configure EN & CS pins to disable CC3100 */
    GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_2);
    GPIOPinTypeGPIOOutput(GPIO_PORTC_BASE, GPIO_PIN_6);
    GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_2, GPIO_PIN_2);
    GPIOPinWrite(GPIO_PORTC_BASE, GPIO_PIN_6, 0);

    /* Configure SSI2 for CC3100 */
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2);
    GPIOPinConfigure(GPIO_PD3_SSI2CLK);
    GPIOPinConfigure(GPIO_PD1_SSI2XDAT0);
    GPIOPinConfigure(GPIO_PD0_SSI2XDAT1);
    GPIOPinTypeSSI(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3);

    /* Configure IRQ pin */
    GPIOPinTypeGPIOInput(GPIO_PORTM_BASE, GPIO_PIN_3);
    GPIOPadConfigSet(GPIO_PORTM_BASE, GPIO_PIN_3, GPIO_STRENGTH_2MA,
                     GPIO_PIN_TYPE_STD_WPD);
    GPIOIntTypeSet(GPIO_PORTM_BASE, GPIO_PIN_3, GPIO_RISING_EDGE);

    SPI_init();
    EK_TM4C129EXL_initDMA();

    WiFi_init();
}

  • Hi Noah,

      Sorry, I'm currently on vacation for the entire week. I will look into your problem when I come back next week. Please expect delays in my response.

  • Have a Happy Holidays!

    I've implemented semaphores between the two tasks, and now, the project sits in the idle task after the "Semaphore_pend(uartSys.sema, BIOS_WAIT_FOREVER);".

    There seems to be a lot going on in "the background" of the tcp task (and I mean all of the functionalities being called to facilitate that TCP operation).  The desired operation is to give the priority to the tcp task, but when there is no connection, nor activity on this task, then I want the uart task to be executed.  

    Here are changes I've made to the two tasks. They are using the same semaphore, which is initialized in another module.

    //=============================================================================
    /**
    @return
    - Void

    Task to handle TCP connection. Can be multiple Tasks running
    this function.
    */
    Void echoFxn
    (
    UArg arg0, ///< TI RTOS argument 0
    UArg arg1 ///< TI RTOS argument 1
    )
    {


    UART_Params uartParams;
    const char echoPrompt[] = "\fEchoing characters:\r\n";

    InitUartParams(&uartParams);

    #ifdef MIKROE_DEV
    UART_Handle uart2, uart4;
    uint32_t count = 0;
    uint32_t size = 0;
    //uint32_t delay = 0;
    char outputString[16];
    char inputString[16];
    static bool initComplete = false;

    //Semaphore_post(uartSys.sema);

    //Task_sleep(GetSleepTickCount());

    /* Loop forever echoing */
    while (1)
    {
    System_printf("Running echoFxn function\n");
    System_flush();

    if (Semaphore_getCount(uartSys.sema) == 0) {
    System_printf("Sem blocked in echoFxn\n");
    System_flush();
    }

    /* Get access to resource */
    Semaphore_pend(uartSys.sema, BIOS_WAIT_FOREVER);

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

    uart2 = UART_open(Board_UART2, &uartParams);
    if (uart2 == NULL) {
    System_abort("Error opening the UART");
    }

    InitUartParams(&uartParams);
    uart4 = UART_open(Board_UART4, &uartParams);
    if (uart4 == NULL) {
    System_abort("Error opening the UART");
    }

    UART_write(uart2, echoPrompt, sizeof(echoPrompt));
    }

    snprintf(outputString, 16, "Count is: %u",count);
    count++;
    size = strlen(outputString);
    UART_write(uart2, outputString, size);
    UART_read(uart4, inputString, 16);

    snprintf(outputString, 16, "%s",inputString);

    System_printf("The string sent was: %s\r\n", outputString);
    System_flush();

    Semaphore_post(uartSys.sema);

    Task_sleep(GetSleepTickCount());

    }
    #else
    char input;
    UART_Handle uart0;

    uart0 = UART_open(Board_UART0, &uartParams);

    if (uart0 == NULL) {
    System_abort("Error opening the UART");
    }

    UART_write(uart0, echoPrompt, sizeof(echoPrompt));

    /* Loop forever echoing */
    while (1) {
    UART_read(uart0, &input, 1);
    UART_write(uart0, &input, 1);
    }
    #endif

    }

    //=============================================================================
    /**
    @return
    - Void

    Task to handle TCP connection. Can be multiple Tasks running
    this function.
    */
    Void tcpWorker
    (
    UArg arg0, ///< task argument 0
    UArg arg1 ///< task argument 1
    )
    {
    int32_t clientfd = (int32_t)arg0;
    int32_t bytesRcvd;
    int32_t 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);
    }
    //=============================================================================
    /**
    @return
    - Void
    Creates new Task to handle new TCP connections.
    */
    Void tcpHandler
    (
    UArg arg0, ///< task argument 0
    UArg arg1 ///< task argument 1
    )
    {
    int32_t status;
    int32_t clientfd;
    int32_t server;
    struct sockaddr_in localAddr;
    struct sockaddr_in clientAddr;
    int32_t optval;
    int32_t optlen = sizeof(optval);
    socklen_t addrlen = sizeof(clientAddr);
    Task_Handle taskHandle;
    Task_Params taskParams;
    Error_Block eb;

    System_printf("Running tcpHandler function\n");
    System_flush();

    if (Semaphore_getCount(tcpTaskSys.sema) == 0) {
    System_printf("Sem blocked in tcpHandler\n");
    System_flush();
    }

    /* Get access to resource */
    Semaphore_pend(tcpTaskSys.sema, BIOS_WAIT_FOREVER);

    server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (server == -1) {
    System_printf("Error: socket not created.\n");
    ShutDown(server);//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");
    ShutDown(server);//goto shutdown;
    }

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

    optval = 1;
    if (setsockopt(server, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0) {
    System_printf("Error: setsockopt failed\n");
    ShutDown(server);//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;
    taskParams.priority = 1;
    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);

    }

    Semaphore_post(tcpTaskSys.sema);

    Task_sleep(GetSleepTickCount());

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

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

  • The problem is when I have both sets of code included, the project will run for about 3 seconds, and the it jumps to abort.

    I'm wondering the amount of system stack you allocate. If you runt the Ethernet and UART individually and see them working then I think the task stack size should be sufficient. It is the system stack that I'm interested to know. What if you increase the system stack. Will it make a difference? Will it still abort? Or it will take longer than 3 seconds to abort? See below where you can change the system stack and heap sizes. Perhaps also increase the task stack and make sure they are sufficient. You can use the ROV to find out the amount of stack that is actually used. 

  • Charles,

    I was able to spend about an hour on this today (certainly not long enough to root cause this). I expanded the system stack to 6,200. And, am examining the ROV, I'm seeing that the idle task is highlighted in red. I'll do some more troubleshooting later, but there's some clue here that I don't fully understand.

  • Charles,

    In short, the problem was that I had included USB logging at some point in my project, but I had forgotten that I had done this. This was what was causing the idle task to be too high and was causing the project to call the abort function. 

    After removing the code pertaining to USB logging, your advice prompted me to investigate why the idle task was being called at all. Afterall, the idle task is only to be called if there are no tasks executing. It turns out that the pending and posting of semaphores had created an unintended dead state, where both the tcp and uart tasks were suspended at the same time.

    I removed all calls to the semaphores. Put both tasks at the same priority, and by using the task sleep function in the uart task, it started working. Both the tcpEcho and the uart are functioning. 

    Other issues were that the uart task had no delay in it, so it was hogging all of the MCU's bandwidth. I added a 10 mSec tasksleep so that the tcp task would be able to be called.

    On a final note, are there any limitations to using snprintf with a task? I observed some strange behavior that seems like a memory leak. I'm going to investigate this more, but wanted to know if there are any limitations from TI's RTOS.

    Thank you for the support!

  • Hi Noah,

      Glad that you are making good progress. 

    On a final note, are there any limitations to using snprintf with a task? I observed some strange behavior that seems like a memory leak. I'm going to investigate this more, but wanted to know if there are any limitations from TI's RTOS

    The snprintf() is a C library function that is used to redirect the output of printf() function onto a buffer.  I don't really see an issue using it. TivaWare library has a simpler version of snprintf which is called usnprintf. Please check out C:\ti\TivaWare_C_Series-2.2.0.295\utils\ustdlib.c file for the various printf functions. I think these simpler functions will take up less memory footprint and hopefully can avoid some of the memory issues you are seeing.