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: "Immediate Bus Fault" when using setCallback function for GPIO interrupt

Part Number: TM4C1294NCPDT
Other Parts Discussed in Thread: SYSBIOS

Hello,

I am using the TM4C1294NCPDT controller with TIRTOS 2.16.0.08 in an application that requires the usage of interrupts on multiple pins. I am getting the issue that, when binding one of the pins' callback functions, the controller crashes immediately on startup. Here the debug log:

[CORTEX_M4_0] Using MAC address in flash
00000.000 ExecStart: Already Open
ti.sysbios.family.arm.m3.Hwi: line 1095: E_hardFault: FORCED
ti.sysbios.family.arm.m3.Hwi: line 1172: E_busFault: PRECISERR: Immediate Bus Fault, exact addr known, address: 85466898
Exception occurred in background thread at PC = 0x0000a3ce.
Core 0: Exception occurred in ThreadType_Task.
Task name: {unknown-instance-name}, handle: 0x200004c8.
Task stack base: 0x20000518.
Task stack size: 0x800.
R0 = 0x200119ac  R8  = 0xffffffff
R1 = 0x85466880  R9  = 0x00000020
R2 = 0x00000000  R10 = 0x00000001
R3 = 0x2001c768  R11 = 0x0200a8c0
R4 = 0x000143ed  R12 = 0x20011828
R5 = 0x00000001  SP(R13) = 0x20000bf0
R6 = 0x0200a8c0  LR(R14) = 0x00005a3f
R7 = 0x2001194c  PC(R15) = 0x0000a3ce
PSR = 0x61000000
ICSR = 0x00423803
MMFSR = 0x00
BFSR = 0x82
UFSR = 0x0000
HFSR = 0x40000000
DFSR = 0x00000001
MMAR = 0x85466898
BFAR = 0x85466898
AFSR = 0x00000000
Terminating execution...

Here is what I am doing in the code. In main.c:

    /* Bind and enable interrupt on the 5th pin */
    GPIO_clearInt(SW_INT);
    GPIO_setCallback(SW_INT, keypadIntCallback);
    //GPIO_enableInt(SW_INT);

Here is what I am doing in EK_TM4C1294XL.c (these items are at the very top of the function, before the other output pins):

    /* Keypad row inputs */
    GPIOTiva_PJ_0 | GPIO_CFG_IN_NOPULL | GPIO_CFG_IN_INT_RISING,    //KPAD_RA
    GPIOTiva_PJ_1 | GPIO_CFG_IN_NOPULL | GPIO_CFG_IN_INT_RISING,    //KPAD_RB
    GPIOTiva_PP_0 | GPIO_CFG_IN_NOPULL | GPIO_CFG_IN_INT_RISING,    //KPAD_RC
    GPIOTiva_PE_4 | GPIO_CFG_IN_NOPULL | GPIO_CFG_IN_INT_RISING,    //KPAD_RD

    /* Switch state interrupt pin */
    GPIOTiva_PK_5 | GPIO_CFG_IN_NOPULL | GPIO_CFG_IN_INT_RISING,    //INT 5

I also have the pins in the correct order in EK_TM4C1294XL.h. Note that, in the main.c function, the interrupt is not even enabled. Simply calling the

GPIO_setCallback(SW_INT, keypadIntCallback);

function causes it to crash. Commenting this line out removes the issue and the controller does not crash.

Using the ROV, I see that Handle 0x200004c8 corresponds to the NS_BootTask with priority 9 which is listed as "Preempted." However, I am not sure what that means. I've read elsewhere on the forums that the crash may be happening because the NS_BootTask is being prematurely interrupted but I do not understand why this would be happening, seeing as that I am only binding the interrupt callback and not actually enabling the interrupt.

Thank you for your support,

svl123

  • Hi,

    Could you attach your .cfg file?

    Todd

  • Please see attached.

    Thanks you.0160.tcpEcho.cfg

  • Hi,

    Could you also attach your EK_TM4C1294XL.c file? Is your array of callback function pointers large enough for the total number of input pins? Does it also crash regardless of which input pin you try to set the callback to like GPIOTiva_PJ_0?

    Jas

  • Hello,

    Please see attached EK_TM4C1294XL.c file.

    /*
     * 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_TM4C1294XL.c ========
     *  This file is responsible for setting up the board specific items for the
     *  EK_TM4C1294XL 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 <IRC_v1.h>
    
    #include "EK_TM4C1294XL.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_TM4C1294XL_usbBusFaultHwi ========
     */
    static Void EK_TM4C1294XL_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_TM4C1294XL_initDMA ========
     */
    void EK_TM4C1294XL_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_TM4C1294XL_initGeneral ========
     */
    void EK_TM4C1294XL_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>
    
    /*
     *  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_TM4C1294XL_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 EMACSnow_HWAttrs emacHWAttrs[EK_TM4C1294XL_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_TM4C1294XL_initEMAC ========
     */
    void EK_TM4C1294XL_initEMAC(void)
    {
        uint32_t ulUser0, ulUser1;
    
        /* 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_PK4_EN0LED0);  /* EK_TM4C1294XL_USR_D3 */
        GPIOPinConfigure(GPIO_PK6_EN0LED1);  /* EK_TM4C1294XL_USR_D4 */
        GPIOPinTypeEthernetLED(GPIO_PORTK_BASE, GPIO_PIN_4 | GPIO_PIN_6);
    
        /* 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_TM4C1294XL.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[] = {
    
        GPIOTiva_PJ_0 | GPIO_CFG_IN_NOPULL | GPIO_CFG_IN_INT_RISING,
        GPIOTiva_PJ_1 | GPIO_CFG_IN_NOPULL | GPIO_CFG_IN_INT_RISING,
        GPIOTiva_PP_0 | GPIO_CFG_IN_NOPULL | GPIO_CFG_IN_INT_RISING,
        GPIOTiva_PE_4 | GPIO_CFG_IN_NOPULL | GPIO_CFG_IN_INT_RISING,
    
        GPIOTiva_PK_5 | GPIO_CFG_IN_NOPULL | GPIO_CFG_IN_INT_RISING,
    
        GPIOTiva_PA_7 | GPIO_CFG_INPUT,
    
        GPIOTiva_PH_2 | GPIO_CFG_INPUT,
    
        GPIOTiva_PN_0 | GPIO_CFG_INPUT,
        GPIOTiva_PP_3 | GPIO_CFG_INPUT,
        GPIOTiva_PP_4 | GPIO_CFG_INPUT,
        GPIOTiva_PP_2 | GPIO_CFG_INPUT,
        GPIOTiva_PM_7 | GPIO_CFG_INPUT,
        GPIOTiva_PM_6 | GPIO_CFG_INPUT,
        GPIOTiva_PM_5 | GPIO_CFG_INPUT,
        GPIOTiva_PM_4 | GPIO_CFG_INPUT,
        GPIOTiva_PM_3 | GPIO_CFG_INPUT,
        GPIOTiva_PM_2 | GPIO_CFG_INPUT,
        GPIOTiva_PM_0 | GPIO_CFG_INPUT,
        GPIOTiva_PQ_4 | GPIO_CFG_INPUT,
    
        GPIOTiva_PD_6 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PD_0 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PD_7 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
    
        GPIOTiva_PD_2 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PD_3 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PQ_0 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PQ_1 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PD_1 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PE_1 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PK_3 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PC_7 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PC_6 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PC_5 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PH_3 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PA_2 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PC_4 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PH_0 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PH_1 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PA_3 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PF_0 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PF_1 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PF_2 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PF_3 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
    
        GPIOTiva_PD_4 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PD_5 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
    
        GPIOTiva_PN_1 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PN_3 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PN_5 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
    
        GPIOTiva_PB_4 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PB_5 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PP_1 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
    
        GPIOTiva_PL_0 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PL_1 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PL_2 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PL_3 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PL_4 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PL_5 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PL_6 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        GPIOTiva_PL_7 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
    
        GPIOTiva_PM_1 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
    
    };
    
    /*
     * Array of callback function pointers
     * NOTE: The order of the pin configurations must coincide with what was
     *       defined in EK_TM4C1294XL.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_TM4C1294XL_USR_SW1 */
        NULL   /* EK_TM4C1294XL_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_TM4C1294XL_initGPIO ========
     */
    void EK_TM4C1294XL_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_TM4C1294XL_I2CCOUNT];
    
    const I2CTiva_HWAttrs i2cTivaHWAttrs[EK_TM4C1294XL_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_TM4C1294XL_initI2C ========
     */
    void EK_TM4C1294XL_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_TM4C1294XL_PWMCOUNT];
    
    const PWMTiva_HWAttrs pwmTivaHWAttrs[EK_TM4C1294XL_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_TM4C1294XL_initPWM ========
     */
    void EK_TM4C1294XL_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_TM4C1294XL_SDSPICOUNT];
    
    const SDSPITiva_HWAttrs sdspiTivaHWattrs[EK_TM4C1294XL_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_TM4C1294XL_initSDSPI ========
     */
    void EK_TM4C1294XL_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_TM4C1294XL_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_TM4C1294XL_SPICOUNT];
    
    const SPITivaDMA_HWAttrs spiTivaDMAHWAttrs[EK_TM4C1294XL_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_TM4C1294XL_initSPI ========
     */
    void EK_TM4C1294XL_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_TM4C1294XL_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_TM4C1294XL_UARTCOUNT];
    
    const UARTTivaDMA_HWAttrs uartTivaHWAttrs[EK_TM4C1294XL_UARTCOUNT] = {
        {
            .baseAddr = UART0_BASE,
            .intNum = INT_UART0,
            .intPriority = (~0),
            .rxChannelIndex = UDMA_CH8_UART0RX,
            .txChannelIndex = UDMA_CH9_UART0TX,
        }
    };
    
    const UART_Config UART_config[] = {
        {
            .fxnTablePtr = &UARTTivaDMA_fxnTable,
            .object = &uartTivaObjects[0],
            .hwAttrs = &uartTivaHWAttrs[0]
        },
        {NULL, NULL, NULL}
    };
    #else
    #include <ti/drivers/uart/UARTTiva.h>
    
    UARTTiva_Object uartTivaObjects[EK_TM4C1294XL_UARTCOUNT];
    unsigned char uartTivaRingBuffer[EK_TM4C1294XL_UARTCOUNT][32];
    
    /* UART configuration structure */
    const UARTTiva_HWAttrs uartTivaHWAttrs[EK_TM4C1294XL_UARTCOUNT] = {
        {
            .baseAddr = UART0_BASE,
            .intNum = INT_UART0,
            .intPriority = (~0),
            .flowControl = UART_FLOWCONTROL_NONE,
            .ringBufPtr  = uartTivaRingBuffer[0],
            .ringBufSize = sizeof(uartTivaRingBuffer[0])
        }
    };
    
    const UART_Config UART_config[] = {
        {
            .fxnTablePtr = &UARTTiva_fxnTable,
            .object = &uartTivaObjects[0],
            .hwAttrs = &uartTivaHWAttrs[0]
        },
        {NULL, NULL, NULL}
    };
    #endif /* TI_DRIVERS_UART_DMA */
    
    /*
     *  ======== EK_TM4C1294XL_initUART ========
     */
    void EK_TM4C1294XL_initUART(void)
    {
        /* UART 0 */
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
        GPIOPinConfigure(GPIO_PA0_U0RX);
        GPIOPinConfigure(GPIO_PA1_U0TX);
        GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
        UARTConfigSetExpClk(UART0_BASE, 120000000, 9600,
                                    (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                                     UART_CONFIG_PAR_NONE));
    
    #ifdef UART1
        /* UART 1 */
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1);
        GPIOPinConfigure(GPIO_PB0_U1RX);
        GPIOPinConfigure(GPIO_PB1_U1TX);
        GPIOPinTypeUART(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    #endif
    
        /* Initialize the UART driver */
    #if TI_DRIVERS_UART_DMA
        EK_TM4C1294XL_initDMA();
    #endif
    
        UART_init();
    
        /* Enables UART FIFO */
        UARTFIFOEnable(UART0_BASE);
    
        /* Set RX FIFO interrupt at maximum and TX interrupt at minimum */
        UARTFIFOLevelSet(UART0_BASE, UART_FIFO_RX6_8, UART_FIFO_TX1_8);
    
        /* Enable the interrupt */
        UARTIntEnable(UART0_BASE, UART_INT_RT | UART_INT_RX);
    
        /* Bind interrupt handler function */
        //UARTIntRegister(UART0_BASE, UART0InterruptHandler); DO NOT DO THIS HERE, DO IN CFG (CREATE HWI)
    
    }
    
    /*
     *  =============================== USB ===============================
     */
    /*
     *  ======== EK_TM4C1294XL_initUSB ========
     *  This function just turns on the USB
     */
    void EK_TM4C1294XL_initUSB(EK_TM4C1294XL_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_TM4C1294XL_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_TM4C1294XL_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_TM4C1294XL_USBMSCHFatFsCOUNT];
    
    const USBMSCHFatFsTiva_HWAttrs usbmschfatfstivaHWAttrs[EK_TM4C1294XL_USBMSCHFatFsCOUNT] = {
        {
            .intNum = INT_USB0,
            .intPriority = (~0)
        }
    };
    
    const USBMSCHFatFs_Config USBMSCHFatFs_config[] = {
        {
            .fxnTablePtr = &USBMSCHFatFsTiva_fxnTable,
            .object = &usbmschfatfstivaObjects[0],
            .hwAttrs = &usbmschfatfstivaHWAttrs[0]
        },
        {NULL, NULL, NULL}
    };
    
    /*
     *  ======== EK_TM4C1294XL_initUSBMSCHFatFs ========
     */
    void EK_TM4C1294XL_initUSBMSCHFatFs(void)
    {
        /* Initialize the DMA control table */
        EK_TM4C1294XL_initDMA();
    
        /* Call the USB initialization function for the USB Reference modules */
        EK_TM4C1294XL_initUSB(EK_TM4C1294XL_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_TM4C1294XL_WATCHDOGCOUNT];
    
    const WatchdogTiva_HWAttrs watchdogTivaHWAttrs[EK_TM4C1294XL_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_TM4C1294XL_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_TM4C1294XL_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_TM4C1294XL_WIFICOUNT];
    
    const WiFiCC3100_HWAttrs wiFiCC3100HWAttrs[EK_TM4C1294XL_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_TM4C1294XL_initWiFi ========
     */
    void EK_TM4C1294XL_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_TM4C1294XL_initDMA();
    
        WiFi_init();
    }
    

    Also, I am binding other GPIO's to the same interrupt callback and they all work without issue. In the main function, I have the following:

        //Clear pending interrupts
        GPIO_clearInt(KPAD_RA);
        GPIO_clearInt(KPAD_RB);
        GPIO_clearInt(KPAD_RC);
        GPIO_clearInt(KPAD_RD);
    
        //Re-bind callback functions
        GPIO_setCallback(KPAD_RA, keypadIntCallback);
        GPIO_setCallback(KPAD_RB, keypadIntCallback);
        GPIO_setCallback(KPAD_RC, keypadIntCallback);
        GPIO_setCallback(KPAD_RD, keypadIntCallback);
    
        //Enable interrupts
        GPIO_enableInt(KPAD_RA);
        GPIO_enableInt(KPAD_RB);
        GPIO_enableInt(KPAD_RC);
        GPIO_enableInt(KPAD_RD);
    
        /* Bind and enable interrupt on the 5th pin */
        GPIO_clearInt(SW_INT);
        GPIO_setCallback(SW_INT, keypadIntCallback);//<----------------------------CAUSES THE CRASH
        //GPIO_enableInt(SW_INT);

    Thank you.

  • Hi,

    There needs to be an entry in the array for each callback function pointer regardless of setting the same callback for all the pins at runtime. You have to update your gpioCallbackFunctions[] array to below:

    GPIO_CallbackFxn gpioCallbackFunctions[] = {
        NULL,   /* KPAD_RA */
        NULL,   /* KPAD_RB */
        NULL,   /* KPAD_RC */
        NULL,   /* KPAD_RD */
        NULL    /* SW_INT */
    };

    Jas

  • HI Jas,

    Thank you! This did indeed solve the problem. However, why did it work when only the first 4 pins were bound to a callback? Why did 4 pins work with only 2 NULL entries in the gpioCallbackFunctions[] array but the 5th caused the problem?

    Thank you.

  • Hi,

    Glad it works now. I am not sure why some of the pins were working before. Is your enum of gpio names in the EK_TM4C1294XL.h in the correct order because it will use that index for the gpioCallbackFunction[] array?

    Jas

  • Hi,

    Yes, the pin order in the .h file matches what is in the .c file.

    svl123