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.

EK-TM4C129EXL: uart_echo demo: Hard Fault on Second UART initialization

Part Number: EK-TM4C129EXL

Tool/software:

I have just broken open my first TM4C eval kit, downloaded CCS  Version: 12.7.1.00001 with tivaware_c_series_2_1_4_178, and Imported/Compiled/Debugged the Example program uart_echo.  So far so good.  But the Example uses UART0, which connects through the builtin USB JTAG probe, and I need a UART with the classic TX and RX pins.  So I thought I would start up UART7 and copy the echo out that UART, and edge into a full implementation that way.  But when I try to initialize UART7 the same way it seems that UART0 is initialized, I get a Hard Fault as soon as the code runs. I don't get the prompt or any echoes on UART0, and when I click Suspend in the debugger, execution is in the FaultISR of startup_ccs.c.  The same thing happens with UART6 instead of UART7.  I added an ISR for UART7 (linked in startup_ccs.s) and it didn't help.  Related posts show UART2 and 7 working together, but on a different processor, and I can't map between them.  Code follows - the important part is near the bottom in main().

//*****************************************************************************
//
// uart_echo.c - Example for reading data from and writing data to the UART in
//               an interrupt driven fashion.
//
// Copyright (c) 2013-2017 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.1.4.178 of the EK-TM4C129EXL Firmware Package.
//
//*****************************************************************************

#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "driverlib/debug.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.
//
//*****************************************************************************

//****************************************************************************
//
// System clock rate in Hz.
//
//****************************************************************************
uint32_t g_ui32SysClock;

//*****************************************************************************
//
// 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, vector set in startup_ccs.c
//
//*****************************************************************************
void UART0IntHandler(void)
{
    uint32_t ui32Status;
    // Get the interrrupt status.
    ui32Status = ROM_UARTIntStatus(UART0_BASE, true);
    // Clear the asserted interrupts.
    ROM_UARTIntClear(UART0_BASE, ui32Status);
    // Loop while there are characters in the receive FIFO.
    while(ROM_UARTCharsAvail(UART0_BASE))
    {
        // Read the next character from the UART and write it back to the UART.
        uint8_t ch = ROM_UARTCharGetNonBlocking(UART0_BASE);
        ROM_UARTCharPutNonBlocking(UART0_BASE, ch);
        //ROM_UARTCharPutNonBlocking(UART7_BASE, ch);                  // <<<<< ECHO to UART 7 TOO!
        // Blink the LED to show a character transfer is occuring.
        GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, GPIO_PIN_0);
        // Delay for 1 millisecond.  Each SysCtlDelay is about 3 clocks.
        SysCtlDelay(g_ui32SysClock / (1000 * 3));
        // Turn off the LED
        GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0);
    }
}

void UART7IntHandler(void)
{
    uint32_t ui32Status;
    // Get the interrrupt status.
    ui32Status = ROM_UARTIntStatus(UART7_BASE, true);
    // Clear the asserted interrupts.
    ROM_UARTIntClear(UART7_BASE, ui32Status);
    // Loop while there are characters in the receive FIFO.
    while(ROM_UARTCharsAvail(UART7_BASE))
    {
        // Read the next character from the UART and write it back to the UART.
        uint8_t ch = ROM_UARTCharGetNonBlocking(UART7_BASE);
        ROM_UARTCharPutNonBlocking(UART7_BASE, ch);
    }
}

//*****************************************************************************
//
// 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.
        ROM_UARTCharPutNonBlocking(UART0_BASE, *pui8Buffer++);
    }
}

void UartSendString(const char * pBuf_p)
{
    UARTSend((const uint8_t*)pBuf_p, strlen(pBuf_p));
}

//*****************************************************************************
//
// This example demonstrates how to send a string of data to the UART, then echo received bytes.
// It is from the Tivaware Examples for EK-TM4C129EXL.
// The example uses UART 0, which connects to PC USB VCP driver through the Stellaris onboard JTAG probe.
// The chip has 8 UARTS.
//
//*****************************************************************************
int main(void)
{
    // Clock Setup from the Example:
    // Set the clocking to run directly from the crystal at 120MHz.
    g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                             SYSCTL_OSC_MAIN |
                                             SYSCTL_USE_PLL |
                                             SYSCTL_CFG_VCO_480), 120000000);
    // Enable the GPIO port that is used for the on-board LED.
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0);
    // Enable the peripherals used by this example.
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    // Enable processor interrupts at the end after everything is set up
    ROM_IntMasterEnable();
    //
    // UART0 Setup from the Example.  UART0 connects through the onboard Stellaris JTAG probe,
    // Set GPIO A0 and A1 as UART0 pins.
    GPIOPinConfigure(GPIO_PA0_U0RX); // 0x00000001 see pin_map.h and Datasheet Table 19-1
    GPIOPinConfigure(GPIO_PA1_U0TX); // 0x00000401
    ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    // Configure the UART for 115,200, 8-N-1 operation.
    ROM_UARTConfigSetExpClk(UART0_BASE, g_ui32SysClock, 115200, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
    // Enable the UART0 interrupt.
    ROM_IntEnable(INT_UART0);
    ROM_UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);
    /* Other UARTs per Datasheet Table 19.1:
     * 1  BLOCKED: Only TX is PB1, captured by debug voltage divider
     * 2  BLOCKED: PA6/PA7 are debug signals; PD6 is used as a chip enable; PD4 is USB_P
     * 3: U3RX@PA4 is FREE at X6-18 and X11-10, maybe also unpop JTAG header,
     *       and U3TX@PA5 is FREE at X6-20 and X11-12, maybe also unpop JTAG header;
     *    Alternate PJ0/1 are user switches
     * 4: U4RX@PK0 is FREE on X6-10 and X11-26, and U4TX@PK1 is FREE on X6-12 and X11-28
     *    Alternate PA2/3 may be free except for voltage dividers used by "booster packs";
     * 5: U5RX@PC6 is FREE on X8-9 and X11-19, and U5TX@PC7 is FREE on X8-15 and X11-17
     * 6: U6RX@PP0 is FREE on X6-5 and X11-54, and U6TX@PP1 is FREE on X6-7 and X11-56
     * 7: U7RX@PC4 is FREE on X11-23 and X8-5, and U7TX@PC5 is FREE on X8-7 and X11-21
     */
    // Follow the demo model to enable UART 6 or 7
#if 0
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART6); // ok
    GPIOPinConfigure(GPIO_PP0_U6RX); // bad
    GPIOPinConfigure(GPIO_PP1_U6TX); // bad
    ROM_GPIOPinTypeUART(GPIO_PORTP_BASE, GPIO_PIN_0 | GPIO_PIN_1); // bad
    ROM_UARTConfigSetExpClk(UART6_BASE, g_ui32SysClock, 115200, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
    ROM_IntEnable(INT_UART6);
    ROM_UARTIntEnable(UART6_BASE, UART_INT_RX | UART_INT_RT);
#endif
#if 1
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART7); // ok
    GPIOPinConfigure(GPIO_PC4_U7RX);
    GPIOPinConfigure(GPIO_PC5_U7TX);
    ROM_GPIOPinTypeUART(GPIO_PORTC_BASE, GPIO_PIN_4 | GPIO_PIN_5); // bad
    ROM_UARTConfigSetExpClk(UART7_BASE, g_ui32SysClock, 115200, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
    ROM_IntEnable(INT_UART7);
    ROM_UARTIntEnable(UART7_BASE, UART_INT_RX | UART_INT_RT);
#endif
    // Application
    // Nonblocking send loses chars  vvvvvvvvv
    UartSendString("Type Characters for Echo: ");
    while(1)
    {
        // Loop forever echoing data through the UART.
    }
}

  • The hard fault hits on line 194: GPIOPinConfigure(GPIO_PC4_U7RX);

    The chip datasheet DS-TM4C129ENCPDT table 19-1 says that UART7 RX/TX are PC4 and PC5 respectively.

  • Hi,

      Let's focus on the below four lines of code, particularly the last three lines. You are trying to configure PC4 and PC5 for UART7 functions but I don't see anywhere you first enable Port C. You need to call  ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC) first.

    #if 1
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART7); // ok
    GPIOPinConfigure(GPIO_PC4_U7RX);
    GPIOPinConfigure(GPIO_PC5_U7TX);
    ROM_GPIOPinTypeUART(GPIO_PORTC_BASE, GPIO_PIN_4 | GPIO_PIN_5); // bad