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-TM4C123GXL: UARTprintf Produces No Output

Part Number: EK-TM4C123GXL


I am new to programming the LaunchPad and have been trying to figure out how to output data/strings to my computer console.  I am mainly using minicom in Linux, but I have also tried using PuTTY in Windows 10. Neither produce any output.  I've read through the utils/uartstdio.c and utils/uartstdio.h source code and simply cannot figure out what I am missing.  Any help would be much appreciated.

Just FYI, I did make sure that minicom and PuTTY were configured for 115200 bps.


The following is my code:

#include <stdbool.h>
#include <stdint.h>
#include "stdlib.h"
#include <stdio.h>

#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_uart.h"

#include "driverlib/gpio.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/pin_map.h"
#include "driverlib/can.h"
#include "driverlib/uart.h"

#include "utils/uartstdio.c"

#define LED_RED GPIO_PIN_1
#define LED_BLUE GPIO_PIN_2
#define LED_GREEN GPIO_PIN_3

void initialize();
void cycle_lights();

int main()
{
    ROM_SysCtlClockSet(SYSCTL_SYSDIV_4|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, LED_RED|LED_BLUE|LED_GREEN);
    ROM_GPIOPinTypeGPIOInput(GPIO_PORTA_BASE, GPIO_PIN_5);

    // Settings for UARTprintf
    ROM_UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
    ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
    ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
    ROM_GPIOPinTypeUART(GPIO_PORTB_BASE, GPIO_PIN_0|GPIO_PIN_1);
    UARTStdioConfig(0, 115200, MAP_SysCtlClockGet());
    

    UARTprintf("DATA INIT");
    initialize();
    for (;;)
    {

        int32_t btn = ROM_GPIOPinRead(GPIO_PORTA_BASE, GPIO_PIN_5);

        UARTprintf("btn %ld\n",btn);

        if(btn != 0)
        {
            cycle_lights();
        }
    }

}

void initialize()
{
    ROM_GPIOPinWrite(GPIO_PORTF_BASE, LED_RED|LED_GREEN|LED_BLUE, LED_GREEN);
}

void cycle_lights()
{
    ROM_SysCtlDelay(50000000);
    ROM_GPIOPinWrite(GPIO_PORTF_BASE, LED_RED, LED_RED);
    ROM_SysCtlDelay(50000000);
    ROM_GPIOPinWrite(GPIO_PORTF_BASE, LED_RED|LED_GREEN|LED_BLUE, LED_RED);
    ROM_SysCtlDelay(100000000);
    ROM_GPIOPinWrite(GPIO_PORTF_BASE, LED_RED|LED_GREEN|LED_BLUE, LED_GREEN);
}

EDIT:  Tried to reorder some things and make it a bit more readable....

EDIT:
- changed UARTStdioConfig(0, 115200, MAP_SysCtlClockGet());" back to "UARTStdioConfig(0, 115200, 16000000);" per Amit's advice.

- Attempted to include "utils/uartstdio.c" via the Makefile, rather than in main.c (see Makefile below).

Here is my Makefile, if it helps diagnosis:

# /tiva-template/Makefile with added source uartstdio.c
# TARGET: name of the output file
TARGET = main
# MCU: part number to build for
MCU = TM4C123GH6PM
# SOURCES: list of input source sources
SOURCES = main.c startup_gcc.c uartstdio.c
# INCLUDES: list of includes, by default, use Includes directory
INCLUDES = -IInclude
# OUTDIR: directory to use for output
OUTDIR = build
# TIVAWARE_PATH: path to tivaware folder
TIVAWARE_PATH = $(HOME)/Embedded/tivaware

# LD_SCRIPT: linker script
LD_SCRIPT = $(MCU).ld

# define flags
CFLAGS = -g -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp
CFLAGS +=-Os -ffunction-sections -fdata-sections -MD -std=c99 -Wall
CFLAGS += -pedantic -DPART_$(MCU) -c -I$(TIVAWARE_PATH)
CFLAGS += -DTARGET_IS_BLIZZARD_RA1
LDFLAGS = -T $(LD_SCRIPT) --entry ResetISR --gc-sections

#######################################
# end of user configuration
#######################################
#
#######################################
# binaries
#######################################
CC = arm-none-eabi-gcc
LD = arm-none-eabi-ld
OBJCOPY = arm-none-eabi-objcopy
RM      = rm -f
MKDIR   = mkdir -p
#######################################

# list of object files, placed in the build directory regardless of source path
OBJECTS = $(addprefix $(OUTDIR)/,$(notdir $(SOURCES:.c=.o)))

# default: build bin
all: $(OUTDIR)/$(TARGET).bin

$(OUTDIR)/%.o: src/%.c | $(OUTDIR)
    $(CC) -o $@ $^ $(CFLAGS)

$(OUTDIR)/a.out: $(OBJECTS)
    $(LD) -o $@ $^ $(LDFLAGS)

$(OUTDIR)/main.bin: $(OUTDIR)/a.out
    $(OBJCOPY) -O binary $< $@

# create the output directory
$(OUTDIR):
    $(MKDIR) $(OUTDIR)

clean:
    -$(RM) $(OUTDIR)/*

.PHONY: all clean

  • Matt McKenna said:

        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);


        ROM_UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
        ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
        ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
        ROM_GPIOPinTypeUART(GPIO_PORTB_BASE, GPIO_PIN_0|GPIO_PIN_1);

    I think the references to GPIO PORTB should be instead for GPIO PORTA, for use by UART0. i.e. try:

        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    
    
        ROM_UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
        ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
        ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
        ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0|GPIO_PIN_1);

  • I already had "ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA)" a few lines up from that.
    I tried replacing "GPIO_PORTB_BASE" with "GPIO_PORTA_BASE" with no change in result.
  • Hi,

    Your code:

    #include "utils/uartstdio.c"

    Don't do that. Include only header files instead. Add the file uartstdio.c to your project either as a local copy either a symbolic link. 

  • Have you tried to check the signals (TX on TM4C side, RX on PC side) with a scope ? That would help to locate the issue - incorrect initialisation, baud rate issues, level/signal issues, etc.

    BTW, I agree with Petrei. Including *.c files is considered bad style - like placing code in headers.

  • Matt,
    I suggest you DO NOT use UARTprintf(). It tends to be "too hardware specific".
    To make your development more flexible, use sprintf() to store your variable text into a string.
    Then, send the string bytes out to your desired serial port. The more simple way of doing that would be with UARTCharPut() inside a while() loop.
    Regards
    Bruno
  • Bruno,

    The suggested implementation looks like this:
    #include <stdio.h>
    #include <math.h>
    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_memmap.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "Uart0.h"

    void Uart0_Configuration(void);

    int main()
    {
    Uart0_Configuration();

    char str[80];
    char *pt_str;

    sprintf(str, "Value of Pi = %f", M_PI);

    pt_str = str; // pointer points to the address of str
    while(*pt_str != '\n'){
    UARTCharPut(UART0_BASE, *pt_str) ;
    pt_str++;
    }

    return(0);
    }




    void Uart0_Configuration(void){

    // Enable the peripherals used by this example.
    // The UART itself needs to be enabled, as well as the GPIO port
    // containing the pins that will be used.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    //
    // Configure the GPIO pin muxing for the UART function.
    // This is only necessary if your part supports GPIO pin function muxing.
    // Study the data sheet to see which functions are allocated per pin.
    // TODO: change this to select the port/pin you are using
    //
    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);

    //
    // Since GPIO A0 and A1 are used for the UART function, they must be
    // configured for use as a peripheral function (instead of GPIO).
    // TODO: change this to match the port/pin you are using
    //
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    //
    // Configure the UART for 115,200, 8-N-1 operation.
    // This function uses SysCtlClockGet() or ui32SysClock to get the system clock
    // frequency. This could be also be a variable or hard coded value
    // instead of a function call.
    //
    #if defined(TARGET_IS_TM4C129_RA0) || \
    defined(TARGET_IS_TM4C129_RA1) || \
    defined(TARGET_IS_TM4C129_RA2)
    UARTConfigSetExpClk(UART0_BASE, ui32SysClock, 115200,
    (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
    UART_CONFIG_PAR_NONE));
    #else
    UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200,
    (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
    UART_CONFIG_PAR_NONE));
    #endif


    }
  • Just be careful also to compare the current byte to the C standard terminator 0x00... and/or to make sure there is a "newline" char on the end of your string - otherwise, it will be sending your whole memory out to the serial port forever!
  • Hello Matt

    The API call

    UARTStdioConfig(0, 115200, MAP_SysCtlClockGet());

    is not correct.You have configured the UART to be sourced from 16MHz PIOSC clock, but are passing the clock frequency as 50MHz for baud rate configuration of 115.2Kbps. It should be

    UARTStdioConfig(0, 115200, 16000000);
  • This has been a source of confusion for me. I don't quite understand why "utils/uartstdio.c" can't be accessed through "utils/uartstdio.h".

    You'll have to excuse my basic c and c++ knowledge base, but are you suggesting literally pasting the source code into my main.c file? Or should I, somehow, create a dependency in my Makefile?
  • Thanks for the information. I had the 16000000 in there originally, but had changed it in a flailing attempt to get something to output to console. I'll change it back.
  • I have not, but thanks for the suggestion. Though, I'm not exactly sure where good probe locations would be, unless I tear apart a USB cable.
  • Bruno and Thiago,

    Thanks for the help! I'll give this a try and let you know my results.
  • I was unable to get your example to work Thiago. For some reason I kept getting an "undefined reference to 'sprintf'". If you have any other thoughts, I am happy to listen. Thanks again.

    I did finally get output. I edited the source code and added the Makefile. Any further tips and helpful criticisms are very welcome. Thanks again!
  • Matt McKenna said:
    I have not, but thanks for the suggestion. Though, I'm not exactly sure where good probe locations would be, unless I tear apart a USB cable.

    If it's the backchannel UART, routed via debug pod and USB, there would only be the TX / RX pins left. Checking those signals would tell you if the initialiation is alright, and the baud rate is proper as well.
  • here, I dont use the UartPrintf, Here Please, try with this sample code. The  best of this approach is you can re-use it by changin the Uart port, from Uart0 to Uart1..

    This function basically put one caracter each time. Put this inside a While loop and you will have a UartString.  See this modified example from Dr. Valvano's Book.

    /*

    This example accompanies the book
    "Embedded Systems: Real Time Interfacing to Arm Cortex M Microcontrollers",
    ISBN: 978-1463590154, Jonathan Valvano, copyright (c) 2015
    Program 5.11 Section 5.6, Program 3.10

    Copyright 2015 by Jonathan W. Valvano, valvano@mail.utexas.edu
    You may use, edit, run or distribute this file
    as long as the above copyright notice remains
    THIS SOFTWARE IS PROVIDED "AS IS". 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.
    VALVANO SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
    OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
    For more information about my classes, my research, and my books, see
    http://users.ece.utexas.edu/~valvano/
    */

    void UART_OutString(uint8_t *pt){
        while(*pt){
            UARTCharPut(UART0_BASE, *pt);
             pt++;
          }
    }


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

    //
    //
    //
    // Copyright (c) 2012-2015 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.2.111 of the EK-TM4C123GXL Firmware Package.
    //
    //*****************************************************************************


    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_memmap.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "Uart0.h"

    void Uart0_Configuration(void){

    // Enable the peripherals used by this example.
    // The UART itself needs to be enabled, as well as the GPIO port
    // containing the pins that will be used.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    //
    // Configure the GPIO pin muxing for the UART function.
    // This is only necessary if your part supports GPIO pin function muxing.
    // Study the data sheet to see which functions are allocated per pin.
    // TODO: change this to select the port/pin you are using
    //
    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);

    //
    // Since GPIO A0 and A1 are used for the UART function, they must be
    // configured for use as a peripheral function (instead of GPIO).
    // TODO: change this to match the port/pin you are using
    //
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    //
    // Configure the UART for 115,200, 8-N-1 operation.
    // This function uses SysCtlClockGet() or ui32SysClock to get the system clock
    // frequency. This could be also be a variable or hard coded value
    // instead of a function call.
    //
    #if defined(TARGET_IS_TM4C129_RA0) || \
    defined(TARGET_IS_TM4C129_RA1) || \
    defined(TARGET_IS_TM4C129_RA2)
    UARTConfigSetExpClk(UART0_BASE, ui32SysClock, 115200,
    (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
    UART_CONFIG_PAR_NONE));
    #else
    UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200,
    (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
    UART_CONFIG_PAR_NONE));
    #endif


    }
    //uart0 test echo user data until \n\r sequence
    void Uart0_test(void){
    char cThisChar;
    //
    // Put a character to show start of example. This will display on the
    // terminal.
    //
    UARTCharPut(UART0_BASE, '!');

    //
    // Enter a loop to read characters from the UART, and write them back
    // (echo). When a line end is received, the loop terminates.
    //
    do
    {
    //
    // Read a character using the blocking read function. This function
    // will not return until a character is available.
    //
    cThisChar = UARTCharGet(UART0_BASE);

    //
    // Write the same character using the blocking write function. This
    // function will not return until there was space in the FIFO and
    // the character is written.
    //
    UARTCharPut(UART0_BASE, cThisChar);
    }
    while((cThisChar != '\n') && (cThisChar != '\r'));

    //
    // Put a character to show the end of the example. This will display on
    // the terminal.
    //
    UARTCharPut(UART0_BASE, '@');

    }