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.

*include "utils/uartstdio.h"* gives error while *include "utils/uartstdio.c"* works fine?

Other Parts Discussed in Thread: EK-TM4C123GXL

Hello,

I've make a simple UART code using LM4F120H5QR.

It works fine, here is the code :

#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.c"

void InitConsole(void)
{
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1);
    ROM_GPIOPinConfigure(GPIO_PB0_U1RX);
    ROM_GPIOPinConfigure(GPIO_PB1_U1TX);
    ROM_GPIOPinTypeUART(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    //UARTConfigSetExpClk(UART1_BASE, ROM_SysCtlClockGet(), 9600,
          //(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
    UARTStdioInitExpClk(1, 9600);
    UARTprintf("UART Initialized...");
    //ROM_SysCtlDelay(2000000);
}


void UARTIntHandler(void)
{
    unsigned long ulStatus;

    ulStatus = ROM_UARTIntStatus(UART1_BASE, true);
    ROM_UARTIntClear(UART1_BASE, ulStatus);

    while(ROM_UARTCharsAvail(UART1_BASE))
    {
        ROM_UARTCharPutNonBlocking(UART1_BASE, ROM_UARTCharGetNonBlocking(UART1_BASE));
        ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2);
        ROM_SysCtlDelay(ROM_SysCtlClockGet() / (1000 * 3));            // Delay for 1 millisecond.  Each SysCtlDelay is about 3 clocks.
        ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);
    }
}

void main(void)
{
    ROM_SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);

    InitConsole();

    ROM_IntMasterEnable();
    ROM_IntEnable(INT_UART1);
    ROM_UARTIntEnable(UART1_BASE, UART_INT_RX | UART_INT_RT);

    while(1){}
}

Here I've include "utils/uartstdio.c" BUT when I use "utils/uartstdio.h" then I am getting these errors:

 undefined           first referenced
  symbol                 in file     
 ---------           ----------------
 UARTStdioInitExpClk ./zigbee.obj    
 UARTprintf          ./zigbee.obj    

error #10234-D: unresolved symbols remain

I've check both the files (.c & .h) and I didn't get why this is happening.

I've defined PART_LM4F120H5QR for pin_map.h file &

TARGET_IS_BLIZZARD_RA1 for rom.h.

I haven't defined any other symbols. I am using ccsv5.3 on win7 32bit.

Though it is working absolutely fine, I want to know why this has happened?

Could someone please make me aware with the reason please?

Thanks for your time.

  • Hi,

    Let the #include utils/uartstdio.h in his place and add to your source folder a symbolic link to the file utils/uartstdio.c (i.e. this means the code in this file must be part of the project, so must be compiled and then the linker will find the missing symbols).

    Petrei

  • I agree change your code to include the "utils/uartstdio.h" and then add "utils/uartstdio.c" to your project.   

  • Stellaris Paul said:
    change your code to include the "utils/uartstdio.h" and then add "utils/uartstdio.c" to your project

    Yes, that's the way to do it!

    This is standard programming stuff - nothing specifically to do with TI or Stellaris.

    Time to brush-up on the distinction between declarations and definitions: http://bit.ly/Sg3oRM

     

  • Thanks for that clear answer Petrei.

    I am sorry for my late response.

    The problem is solved... and the answer is already verified by TI employee.

    But I've one last doubt regarding this.

    Why this has happened, and that also why with only  " uartstdio.c " ??

    Am I making any mistake? or is it a bug of ccs? or any other reason ??

    Could you please clear me with this?

    Thanks for your time.

  • Hi,

    No, it's not your mistake, neither bug in ccs - the authors of this package cannot predict all possible uses/needs of every user in the world - so sometimes you need to manage the path and the content of your project(s). On the other side, you made your project where on disk? if you made it outside of StellarisWare/boards/your_board then you must expect other changes, like possible new include paths. Take two projects from StelarisWare and check their settings - paths, defines, options. Look to a project which uses lwip and you will understand.

    Petrei 

  • I am also struggling to understand the behaviour here. I have read the info provided in the previous posts but I still cannot figure out why some files need to be linked and others do not. 

    For example :-

    uartstdio.h & uartstdio.c are both located in ../StellarisWare/utils/
    I have the StellarisWare folder added to the includes path and I have added #include “utils/uartstdio.h” in my source file. Unless I add uartstdio.c to the project as a linked file I get unresolved symbol errors on calls to functions in uartstdio.c 

    I am also using can.h & can.c located in ../StellarisWare/driverlib/
    I have added #include “driverlib/can.h” to my source file and it compiles fine without the need to specifically add can.c as a linked file. 

    While it is not hard to at uartstdio.c as a linked file I would like to understand where the difference is. If anyone can nudge me in the right direction I would appreciate it.

    Alastair

  • You should never #include a *.c file.  A *.c file should be compiled by itself, then linked into the project.  When you #include a *.c file, you are basically inserting that file into another source file as far as the compiler is concerned.  While that may work, it's not a particularly good way to program, and is prone to causing very hard to sort out problems later in life when you are likely to get namespace collisions.  For instance, if you have two source files that refer to functions in xyz.c, and they both attempt to #include xyz.c, the functions will be created twice, and will cause linker errors.

    *.h files are header files, and provide the defines and interfaces so that you can refer to functions and variables that are contained elsewhere.

    If you need to access the functions in uartstdio.c, there are two things you need to do.  You need to have uartstdio.c compiled and linked as part of your project, and you need to #include the header file uartstdio.h in every source file that refers to a function or variable from uartstdio.c.  How you get the file added to your project varies from IDE to IDE.

    What you don't realize about the driverlib source files is that they are all compiled and then linked into the driverlib library, and that whole library is then being linked into your project.  That's why you don't have to add the specific source files to your project, you just need to have files #include the header files for the functions they need access to.  The advantage of a library is that functions that you don't call in the library don't get added to your code, only the functions that you actually make reference to get linked in.  Other source files in your project that are built and linked in will generate code for every function in your application whether or not you call the functions.

  • slandrum said:
    What you don't realize about the driverlib source files is that they are all compiled and then linked into the driverlib library, and that whole library is then being linked into your project

    Thanks slandrum, I think that was the bit of info I needed so that I can make sense of what is happening.

  • slandrum said:
    *.h files are header files, and provide the defines and interfaces so that you can refer to functions and variables that are contained elsewhere.

    Note that this has nothing specifically to do with TI or Stellaris - this is how 'C' works in any environment.

    As slandrum says, so-called "header" files specify the interface, but do not (or should not) provide the implementation - that comes from the .c file (or library).

    http://c-faq.com/decl/decldef.html

    slandrum said:
    If you need to access the functions in uartstdio.c, there are two things you need to do.  You need to have uartstdio.c compiled and linked as part of your project, and you need to #include the header file uartstdio.h in every source file that refers to a function or variable from uartstdio.c.

    Correct.

    However, if you do #include the .c file, then your are effectively pasting its entire content into your own file - thus your own file effectively contains all the functions from the included file, and no external linking is required!

     

  • Going back to the title of this thread:

    #include "utils/uartstdio.h"* gives error while #include "utils/uartstdio.c"*  works fine?

    It is hopefully now clear that #include-ing just the header file is not the thing that actually caused the error - it was the fact that the .c file was missing from the project which caused the error.

    #include-ing the .c file had the same net effect as having the .c file in the project - hence no error in that case.

     

     

  • Hi,

    Maybe is OK with this particular example - but please do not forget/neglect the visibility problems and what will happen if the user needs to include this .c file in multiple other(s) files for calling different functions.

    Petrei 

  • Petrei said:
    Maybe is OK with this particular example

    To be clear, I am not advocating this as a practice to follow or encourage - merely pointing out how it explains the symptoms observed!

    As a general rule - with very few exceptions - do not  #include .c files!!

     

  • Sorry, to revisit this but I'm having the same issue. New user to the Tiva C EK-TM4C123GXL launch pad (long time user of the MSP430 launchpad).

    I've copied the example timer project and now trying to get UARTPeek working to read in UART commands from a PC.

    The project properties has link to utils/UARTstdio.c and I have the following lines in my code:

    #define UART_BUFFERED // buffered UART operation
    #include "utils/uartstdio.h"

    however I get compiler error :

    unresolved symbol UARTPeek, first referenced in ./base.obj	!base		 

    I've wasted 3 hours trying to find a solution....

  • just to add, if I use "add files..." to add UARTstdio.c to my project then I get errors that all the basic UART functions are being redefined (AND UARTPeek is unresolved)....

  • Hi,

    The function UARTPeek(..) is declared as below in the file uartstdio.c:
    #if defined(UART_BUFFERED) || defined(DOXYGEN)
    int
    UARTPeek(unsigned char ucChar)
    {
    ....

    }
    so if still not found by the compiler/linker, then seems your UART_BUFFERED declaration is misplaced. It should not be inside the code; doing that will allow only local options to be solved, but should be globally visible at compile/link time, so it is better to place it to the pre-defined symbols tab.
    Keep in mind that any compilation is a new process, which should be done with the right options (the latest Eclipse implementations allow even parallel compilations to reduce processing time).

    Also, adding files to project must be made with care - a file can be added locally to the project or as a symbolic link, resulting in further different declarations.

    Petrei

  • Petrei,

    wow - thank you. I would never have found / guessed that. I guess it would be helpful that that is spelled out in the documentation for UARTstdio (It says to define UART_BUFFRED, just not where to define it).

    I made that change (and removed the local link of UARTstdio.c) and it compiles fine now.

    Again, many thanks.