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.

TM4C123GH6PM: Random FaultISR()

Part Number: TM4C123GH6PM
Other Parts Discussed in Thread: EK-TM4C123GXL

Tool/software:

I have a TI Tiva TM4C123GH6PMIR on a custom board that is giving me all kind of random FaultISR() at different lines of code.

No matter what I have tried I can't seen to narrow down what is causing the problem.

My code is based off the uart_echo example.

My code is here,

/*
 * main.c
 *
 *  Created on: Jul 4, 2024
 *      Author: User
 */
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"

#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif

void GPIOPinUnlockGPIO(uint32_t ui32Port, uint8_t ui8Pins)
{
    HWREG(ui32Port + GPIO_O_LOCK) = GPIO_LOCK_KEY;      // Unlock the port
    HWREG(ui32Port + GPIO_O_CR) |= ui8Pins;             // Unlock the Pin
    HWREG(ui32Port + GPIO_O_LOCK) = 0;                  // Lock the port
}

//*****************************************************************************
//
// The UART interrupt handler.
//
//*****************************************************************************
void
UARTIntHandler(void)
{
    uint32_t ui32Status;

    //
    // Get the interrrupt status.
    //
    ui32Status = UARTIntStatus(UART0_BASE, true);

    //
    // Clear the asserted interrupts.
    //
    UARTIntClear(UART0_BASE, ui32Status);

    //
    // Loop while there are characters in the receive FIFO.
    //
    while(UARTCharsAvail(UART0_BASE))
    {
        //
        // Read the next character from the UART and write it back to the UART.
        //
        UARTCharPutNonBlocking(UART0_BASE,
                                   UARTCharGetNonBlocking(UART0_BASE));

        //
        // Blink the LED to show a character transfer is occurring.
        //
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2);

        //
        // Delay for 1 millisecond.  Each SysCtlDelay is about 3 clocks.
        //
        SysCtlDelay(SysCtlClockGet() / (1000 * 3));

        //
        // Turn off the LED
        //
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);

    }
}

//*****************************************************************************
//
// Send a string to the UART.
//
//*****************************************************************************
void
UARTSend(const uint8_t *pui8Buffer, uint32_t ui32Count)
{
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, GPIO_PIN_2);
    //
    // Loop while there are more characters to send.
    //
    while(ui32Count--)
    {
        //
        // Write the next character to the UART.
        //
        UARTCharPut(UART0_BASE, *pui8Buffer++);
    }

    while (UARTBusy(UART0_BASE))
    {

    }

    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0);
}



int main()
{

    //0. Enable lazy stacking for interrupt handlers.
    FPUEnable();
    FPULazyStackingEnable();

    //1. Run from the internal oscillator.
    SysCtlClockSet(SYSCTL_OSC_INT | SYSCTL_USE_OSC | SYSCTL_SYSDIV_1);

    //2. Enable the peripherals.
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA))
    {
    }

    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_UART0))
    {
    }

    //3. Set GPIO A0 and A1 as UART pins.
    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    //4. Configure UART
    UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200,
                                (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                                 UART_CONFIG_PAR_NONE));

    //5. Enable the UART interrupt.
    IntEnable(INT_UART0);
    UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);

    //6. Enable the GPIO Pins.
    GPIOPinUnlockGPIO(GPIO_PORTA_BASE, GPIO_PIN_2);
    GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_2); //TX EN
    GPIOPinUnlockGPIO(GPIO_PORTA_BASE, GPIO_PIN_3);
    GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_3); //RX EN

    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0); //UART_TX_EN (Active High)
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, 0); //UART_RX_EN (Active Low)



    //7. Enable the processor interrupts.
    IntMasterEnable();

    while(1)
    {
        UARTSend((uint8_t *)"\033[2JEnter text: ", 16);
    }

}

My code is jumping into FaultISR() from IntMasterEnable() and from GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, GPIO_PIN_2);

I have no idea what is going on. Any advice would be greatly appreciated.

Thanks,

Allan

  • I attempted to run the uart_echo example on the custom board only changing the clock source.

    //*****************************************************************************
    //
    // uart_echo.c - Example for reading data from and writing data to the UART in
    //               an interrupt driven fashion.
    //
    // Copyright (c) 2012-2020 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    // 
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    // 
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    // 
    // This is part of revision 2.2.0.295 of the EK-TM4C123GXL Firmware Package.
    //
    //*****************************************************************************
    
    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/debug.h"
    #include "driverlib/fpu.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    
    //*****************************************************************************
    //
    //! \addtogroup example_list
    //! <h1>UART Echo (uart_echo)</h1>
    //!
    //! This example application utilizes the UART to echo text.  The first UART
    //! (connected to the USB debug virtual serial port on the evaluation board)
    //! will be configured in 115,200 baud, 8-n-1 mode.  All characters received on
    //! the UART are transmitted back to the UART.
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************
    #ifdef DEBUG
    void
    __error__(char *pcFilename, uint32_t ui32Line)
    {
    }
    #endif
    
    //*****************************************************************************
    //
    // The UART interrupt handler.
    //
    //*****************************************************************************
    void
    UARTIntHandler(void)
    {
        uint32_t ui32Status;
    
        //
        // Get the interrrupt status.
        //
        ui32Status = MAP_UARTIntStatus(UART0_BASE, true);
    
        //
        // Clear the asserted interrupts.
        //
        MAP_UARTIntClear(UART0_BASE, ui32Status);
    
        //
        // Loop while there are characters in the receive FIFO.
        //
        while(MAP_UARTCharsAvail(UART0_BASE))
        {
            //
            // Read the next character from the UART and write it back to the UART.
            //
            MAP_UARTCharPutNonBlocking(UART0_BASE,
                                       MAP_UARTCharGetNonBlocking(UART0_BASE));
    
            //
            // Blink the LED to show a character transfer is occuring.
            //
            GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2);
    
            //
            // Delay for 1 millisecond.  Each SysCtlDelay is about 3 clocks.
            //
            SysCtlDelay(SysCtlClockGet() / (1000 * 3));
    
            //
            // Turn off the LED
            //
            GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);
    
        }
    }
    
    //*****************************************************************************
    //
    // Send a string to the UART.
    //
    //*****************************************************************************
    void
    UARTSend(const uint8_t *pui8Buffer, uint32_t ui32Count)
    {
        //
        // Loop while there are more characters to send.
        //
        while(ui32Count--)
        {
            //
            // Write the next character to the UART.
            //
            MAP_UARTCharPutNonBlocking(UART0_BASE, *pui8Buffer++);
        }
    }
    
    //*****************************************************************************
    //
    // This example demonstrates how to send a string of data to the UART.
    //
    //*****************************************************************************
    int
    main(void)
    {
        //
        // Enable lazy stacking for interrupt handlers.  This allows floating-point
        // instructions to be used within interrupt handlers, but at the expense of
        // extra stack usage.
        //
        MAP_FPUEnable();
        MAP_FPULazyStackingEnable();
    
        //
        // Set the clocking to run directly from the crystal.
        //
    //    MAP_SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
    //                       SYSCTL_XTAL_16MHZ);
    
        SysCtlClockSet(SYSCTL_OSC_INT | SYSCTL_USE_OSC | SYSCTL_SYSDIV_1);
    
        //
        // Enable the GPIO port that is used for the on-board LED.
        //
        //MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    
        //
        // Enable the GPIO pins for the LED (PF2).
        //
        //MAP_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);
    
        //
        // Enable the peripherals used by this example.
        //
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
        //
        // Enable processor interrupts.
        //
        MAP_IntMasterEnable();
    
        //
        // Set GPIO A0 and A1 as UART pins.
        //
        GPIOPinConfigure(GPIO_PA0_U0RX);
        GPIOPinConfigure(GPIO_PA1_U0TX);
        MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //
        // Configure the UART for 115,200, 8-N-1 operation.
        //
        MAP_UARTConfigSetExpClk(UART0_BASE, MAP_SysCtlClockGet(), 115200,
                                (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                                 UART_CONFIG_PAR_NONE));
    
        //
        // Enable the UART interrupt.
        //
        MAP_IntEnable(INT_UART0);
        MAP_UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);
    
        //
        // Prompt for text to be entered.
        //
        UARTSend((uint8_t *)"\033[2JEnter text: ", 16);
    
        //
        // Loop forever echoing data through the UART.
        //
        while(1)
        {
        }
    }
    

    The code does work on the ek-tm4c123gxl launchpad, but does not work on the custom board.

    When I run the uart_echo example on the custom board I get a NVIC_FAULT_STAT_IMPRE (1) count.

    Any advice on how to debug this further?

    Thanks,

    Allan

  • Hello Allan,

    That is a very unusual issue. I am surprised you'd be seeing that sort of trouble.

    If it is possible for you to share the MCU schematic, that could be reviewed for potential issues. You can also look into the HW guidelines we have for this device: https://www.ti.com/lit/pdf/spma059

    You should also double check that you have a TM4C123x device and not a TM4C129x device populated on your custom board as they have different clock setups.

    Beyond that, I am a bit stumped myself and would need to defer the usual expert for this topic.

    Unfortunately, they have been impacted by Hurricane Beryl and may not be able to reply for multiple days. So if I am unable to help resolve this, please understand that further support may be delayed.

    Best Regards,

    Ralph Jacobi

  • Hi Ralph,

    Thanks for the reply. The MCU schematic is attached. I double checked and I do have a TM4C123x device mounted. I have two custom boards and they both have the same issue. I have used the MCU schematic for other designs and haven't had any issues. The schematic shows a TM4C1231D5PMT, but I am using a TM4C123GH6PMIR as an alternate. 3566.MCU_SCH.pdf

    Thanks,

    Allan

  • Hello Allan,

    What are the capacitor values for C1 through C8?

    Best Regards,

    Ralph Jacobi

  • Hi Ralph,

    The capacitor values for C1 through C8 are,

    C1 -> 0.1uF

    C2 -> 1uF

    C3 -> 2.2uF

    C4 -> 1uF

    C5 -> 1uF

    C6 -> 1uF

    C7 -> 1uF

    C8 -> 1uF

    Thanks,

    Allan

  • Hi Allan,

    I see, those are all okay as far as cap values are concerned. I'm going to have to loop in the usual expert for these devices to help work this further. Maybe I overlooked something.

    Best Regards,

    Ralph Jacobi

  • Hi,

      The problem is that in your line 160, you commented out MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF). But in your UARTIntHandler(), you are trying to set GPIOF.2 in line 98. Your line 98 has the below code. When this line is executed without first enabling portF as expected in line 160, you will get a exception fault. This is a expected behavior. You need to uncomment line 160. 

    GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2);

    I don't have any problem running your code after I uncomment line 160. 

  • Hi Charles,

    That was it. I can't believe I didn't see it. Good catch!

    I changed the UART interrupt handler to this,

    //*****************************************************************************
    //
    // The UART interrupt handler.
    //
    //*****************************************************************************
    void
    UARTIntHandler(void)
    {
        uint32_t ui32Status;
    
        //
        // Get the interrrupt status.
        //
        ui32Status = MAP_UARTIntStatus(UART0_BASE, true);
    
        //
        // Clear the asserted interrupts.
        //
        MAP_UARTIntClear(UART0_BASE, ui32Status);
    
        //
        // Loop while there are characters in the receive FIFO.
        //
        while(MAP_UARTCharsAvail(UART0_BASE))
        {
            //
            // Read the next character from the UART and write it back to the UART.
            //
            MAP_UARTCharPutNonBlocking(UART0_BASE,
                                       MAP_UARTCharGetNonBlocking(UART0_BASE));
    
            //
            // Blink the LED to show a character transfer is occuring.
            //
            //GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2);
    
            //
            // Delay for 1 millisecond.  Each SysCtlDelay is about 3 clocks.
            //
            SysCtlDelay(SysCtlClockGet() / (1000 * 3));
    
            //
            // Turn off the LED
            //
            //GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);
    
        }
    }

    Thanks,

    Allan