NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » The dreaded "undefined reference" error

February 04, 2012
by amartinez
amartinez's Avatar

Guys, I really need to understand this. As you know I use AVR Studio programming with SPI and in using code from Nerdkits, I keep getting the dreaded “undefined reference” error.

Here’s the code in question giving me the undefined reference error

lcd_home(); fprintf_P(&lcd_stream, PSTR("Raw: %7.2f"), temp_avg);

The header file “lcd.h” is called up but from the AVR Studio include files not the nerdkits.

Here’s where I just don’t get it.

AVR Studio’s lcd.h file contains the following

/*

 * Stdio demo, upper layer of LCD driver.
 *
 * $Id: lcd.h 1008 2005-12-28 21:38:59Z joerg_wunsch $
 */

/*
 * Initialize LCD controller.  Performs a software reset.
 */
void    lcd_init(void);

/*
 * Send one character to the LCD.
 */
int lcd_putchar(char c, FILE *stream);

Now, Nerdkits lcd.h looks totally different

    #ifndef __LCD_H
    #define __LCD_H

        void lcd_set_type_data();
    void lcd_set_type_command();
void lcd_write_nibble(char c);
void lcd_write_byte(char c);
void lcd_clear_and_home();
void lcd_home();
void lcd_write_data(char c);
void lcd_write_int16(int16_t in);
void lcd_write_int16_centi(int16_t in);
void lcd_write_string(const char *x);
void lcd_line_one();
void lcd_line_two();
void lcd_line_three();
void lcd_line_four();
void lcd_goto_position(uint8_t row, uint8_t col);
void lcd_init();

#include <stdio.h>
int lcd_putchar(char x, FILE *stream);

#endif

Is this why I’m getting such errors? Everything works except these undefined reference errors. I find myself writing code from scratch which is a good thing but when I want to try something out then take it apart and follow what it’s doing, I find myself for days trying to circumvent this undefined reference problem.

What is it referencing? Any links to explaining exactly what these header files do? I noticed most of them have a similar name but have very different code and sometime include other header files.

Thanks

February 04, 2012
by Rick_S
Rick_S's Avatar

Why don't you just use the Nerdkit library? It's a very simple basic library. If you are determined to use AVRStudio, I believe all you have to do is place the library files you want in your project folder and include them instead of the avr-gcc libraries.

February 04, 2012
by pcbolt
pcbolt's Avatar

Hi Al,

When the compiler takes your C-code and turns it into machine language, it needs to know how to call functions that are not defined in your source code but from some external library or object file. When you call "lcd_home()" for example, it need to know there are no arguments to allocate for and that it returns no value (void). So you have to put a statement in the source code file to tell it where to find the format or prototype for "lcd_home()", and that place is in the .h header files. So it looks like AVRStudio is searching for lcd.h in its default location and can't find the prototype for "lcd_home()" because it's not there. You can override that by giving it the absolute (or relative) path to the NerdKit's lcd.h location. BTW the linker also needs to know that location as well, since it will need the lcd.o file to insert the actual function code into your final executable file.

February 05, 2012
by amartinez
amartinez's Avatar

Rick, I copied the Nerdkit library and added it to the AVR directory. I point to those .h files in my code but I get the same result. What I may have to do is rename the AVR library .h files like lcd.h to lcd_avr.h then copy the nerdkit lcd.h to that directory. I then have to deal with the .o files I guess, that's another mistery (or misery). In short, I have done that already.

PCBolt, very informative info. I will do what I mentioned to Rick and hopefully that will work. One question. arent the .o files derived from the .h files once they are compiled from a .c file? In other words, compiling your own header lcd.c makes an lcd.o and lcd.h file. I also noticed the .h file calling other .h files within, I may have to change all of them. I may take a second computer and load the AVR Studio 5 and play with that.

February 05, 2012
by Rick_S
Rick_S's Avatar

Don't add it to the avr directory, put it in your project folder or as PCBolt said, put the full path in your include statement. This should force it to use the correct one.

February 05, 2012
by Ralphxyz
Ralphxyz's Avatar

Al, you are probable having a "pathing" problem. Like Rick said just put it in your include statement but you have to have the correct path!

You do not have to do any coping or moving of the files including the libnerdkit files IF you have the correct path!

Ralph

February 06, 2012
by pcbolt
pcbolt's Avatar

Hi Al,

Actually, object files (i.e. lcd.o) are created from source code files (lcd.c). Header files (lcd.h) are not compiled at all. They are created manually and are used to help you use pre-existing code. They might contain function prototypes, pre-defined macros, pin definitions, global variables etc. They also tell the linker to look for the object files (lcd.o) with the same name as the header files (without the .h extention of course). You'll notice in all the Nerdkit projects the source code you create (i.e. led_blink.c) first get compiled into object files (led_blink.o). There is no led_blink.h because you're not creating any functions or variables to be used by any other programs. Since the led_blink.c file does use outside references, it includes a few header files (i.e. avr/io.h for pin definitions). The linker then comes along and takes your object file (which is machine code specific to your program) and links it with any object file or library listed in the include statements. It sees for example "include avr/io.h" and knows to look for "io.o" or "io.lib" in the "avr" directory. So the include files help the compiler with function prototypes and variable definitions, then help the linker find the object files to link with.

Hope this helps.

February 08, 2012
by amartinez
amartinez's Avatar

I did use the correct path, I date back to the DOS days, paths are groovy (I just dated myself)... I added an NK directory to the AVR and copied all the nerkid files in it in order then mythotically pointed to every header file in the NK directory.

I think my problem is with the linker but I will retry the path using different marks. I was doing research on the net and it seems that code using the < > marks looks for header files in the default directory (I guess it ignores paths), so if I use " " marks instead of < > the path should work. My research states that the quotation marks FORCE the compiler to use a specified path. We'll see.

February 08, 2012
by Rick_S
Rick_S's Avatar

That is 100% true, for your own libraries you enclose them in "" quotes instead of the <> greater than less than symbols. If you look at the original files from the code download, you'll see something similar to the following:

#define F_CPU 14745600

#include <stdio.h>
#include <math.h>

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>

#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"
#include "../libnerdkits/uart.h"

You can see the NerdKits guys included their libraries in quotes and the Standard libraries in greater/less than symbols.

Rick

February 08, 2012
by amartinez
amartinez's Avatar

Rick. This forum is absolutely awesome. Thanks much buddy. I didn't think too much about the quotation marks until I did some research. Thanks for verifying. Now to the keyboard, just call me code monkey.

February 10, 2012
by amartinez
amartinez's Avatar

Ok.. still not working.. here's the problem.

I've been working on the header file directory pointers as described in the above posts. I used <> signs and "" signs and I still get the same "undefined reference to" problem

In the AVR Studio application, I went to options and used the Win_AVR make.exe instead of AVR Studio's make.exe... same problem

I changed the tool library path to point to the Nerdkit header and subdirectory structure, same problem

I know I hit the actual header files or AVR Studio tells me there is no file in such a directory. The files are there, they are being hit, their are being read (assumption), why do I get this consistent undefined reference to problem?

Let's pick on the first problem undefined reference to `ledarray_all_off'

When I do a search I can't find this function in any header file in the nerdkit directory, but I may not have a real grasp of what `ledarray_all_off' really means. I'm thinking it's a function call?

In the ledarray.c source code on line 100 I see the command

   ledarray_all_off();

That's a function call am I correct? If so, where is it in the header files? I don't see such a function in the ledarray.c code.

JUST AXING IS ALL.. I'M BEFUTTLED....

Here is an excerpt of the error log generated by AVR Studio, I cut it short because of the same " undefined reference to " error over and over,

I called my project (AVR speak) NK_LED_ARRAY_TEST but the program used is the Nerdkits ledarray.c

Finished building: .././NK_LED_ARRAY_TEST.c Building target: NK_LED_ARRAY_TEST.elf Invoking: AVR/GNU C/C++ Linker "C:/Program Files/Atmel/AVR Studio 5.0/AVR ToolChain/bin/avr-gcc.exe" -mmcu=atmega168 -Wl,-Map=NK_LED_ARRAY_TEST.map -o NK_LED_ARRAY_TEST.elf NK_LED_ARRAY_TEST.o
NK_LED_ARRAY_TEST.o: In function __vector_16': C:\Documents and Settings\al\My Documents\AVRStudio\NK_LED_ARRAY_TEST\NK_LED_ARRAY_TEST\Debug/.././NK_LED_ARRAY_TEST.c(100,1): undefined reference toledarray_all_off'

C:Documents and SettingsalMy DocumentsAVRStudioNK_LED_ARRAY_TESTNK_LED_ARRAY_TESTDebug/.././NK_LED_ARRAY_TEST.c(112,1): undefined reference to `ledarray_get'

C:Documents and SettingsalMy DocumentsAVRStudioNK_LED_ARRAY_TESTNK_LED_ARRAY_TESTDebug/.././NK_LED_ARRAY_TEST.c(112,1): undefined reference to `ledarray_set_columndriver'

C:Documents and SettingsalMy DocumentsAVRStudioNK_LED_ARRAY_TESTNK_LED_ARRAY_TESTDebug/.././NK_LED_ARRAY_TEST.c(121,1): undefined reference to `ledarray_get'

C:Documents and SettingsalMy DocumentsAVRStudioNK_LED_ARRAY_TESTNK_LED_ARRAY_TESTDebug/.././NK_LED_ARRAY_TEST.c(187,1): undefined reference to `uart_getchar'

    collect2: ld returned 1 exit status
    make: *** [NK_LED_ARRAY_TEST.elf] Error 1
Done executing task "RunAvrGCC" -- FAILED.

Done building target "CoreRebuild" in project "NK_LED_ARRAY_TEST.avrgccproj" -- FAILED. Done building project "NK_LED_ARRAY_TEST.avrgccproj" -- FAILED.

I know this is not an AVR Studio forum but I hope someone out there is using native Atmel products, maybe someone can help? I'm at my wits end... pulling my monkey hair out!

February 10, 2012
by Rick_S
Rick_S's Avatar

ledarray_all_off() is in the ledarray.c file not in any of the header files. On a fresh download, it's the 4th function from the top.

If you don't have it in your ledarray.c, it's either because you accidentally deleted it or it's there and you just missed it.

Also, when posting code or text responses from the compliler, please select it and the press the indent selection as code block button. It will format it so it is much more readable.

Rick

February 10, 2012
by amartinez
amartinez's Avatar

Rick. Thanks, I now see the function as well, I got crosseyed. But why does the error keep coming up in reference to that function call as well as others? Ok, so it should work but it doesn't.

In doing research in this forum I found another post with a similar problem and the end result was "rewrite the code". I may have to get to that point because I have no idea what's going on here yet I'd rather follow the nerdkit way using my AVR Dragon. Maybe that's not possible in a native Atmel environment.

The download is fresh, the pointers to the header files have been tried using various methods and I even used the win_avr make.exe file as well. I'm back to square one all the times.

Other than rewriting the code, I'm opened to suggestions.

Thanks

February 10, 2012
by Rick_S
Rick_S's Avatar

You can still use your dragon w/o using the AVR Studio software. Avrdude will upload through the dragon.

February 11, 2012
by amartinez
amartinez's Avatar

Thanks Rick,

I know what you're saying but AVR Studio uploads the bootloader and has some excellent programming features. What did work for me before was uploading the hex files made by Avrdude through the dragon using SPI. I could go that route but that would not solve my existing problem.

I'm starting to work with other chips like the Atiny and AVR Studio / Dragon plaform which supports that chipset with its own firmware bootloaders. I may go all out beyond the 328 at one point, I don't know, but since I've been introduced to Atmel I would rather work within its environment.

I'm going to do some more research on this problem. Thanks all for your help.

Al

February 11, 2012
by Rick_S
Rick_S's Avatar

No problem at all. It all gets the same job done using the same root tools. If you prefer the Atmel gui and project management over something else I have absolutely no problem with it.

Just keep in mind, just because you are using the AVR Studio software, doesn't mean you are developing with Atmel compilers. Unless you are programming in assembler, you are using the same toolset as the rest of us just with a different gui. Also, understand that when you are uploading via the dragon, you are not using any bootloader. You are using a built in hardware serial or parallel programming method. Bootloaders actually use some of the program memory to do their thing, programming via the SPI bus or via the parallel method does not use any program memory and leave it all free for your own code.

Most if not all attiny micro's do not use a bootloader either, and are either programmed via the SPI with an ISP programmer or TPI protocol. Again, if you are programming those in C, you will be using the same tools.

The advantage you see in using the AVR Studio GUI can also be a crutch in that you don't see what goes on behind the scenes as well. When that happens, you run into the problems you are. Because now instead of you calling all the shots in your code and makefile, you are allowing their software to do what it "thinks" you want it to. That is the main reason from what I've read that the NerdKit guys shy away from promoting AVR Studio. Rather, they have you learn in the most complicated method possible... the command line. However, once you do things the hard way for a while, it gives you a little more insight to how things work together. Then if you want to move to other options, whether it be Programmers Notepad, or AVR Studio, you have a better grasp of the overall picture.

I do use AVR Studio on occasion. It comes in handy for seeing how many clock cycles certain functions will take to run, it's great for assembler programs, and given the hardware you have (Your Dragon), if you have an mcu with JTAG you can do on chip debugging. So believe me, I'm no knocking it one bit. It's a tool like many others. We all have to use the one's that best fit us. The Nerdkit guys start us out with a hand saw and hammer, Jumping straight to AVR Studio may be more like a Power saw with an Air nailer.... More power, more complex to use, but makes the job easier once you have developed the skils to use it well.

Rick

February 11, 2012
by amartinez
amartinez's Avatar

That's the essence of engineering, I agree Rick. I see your point. To use an O/S analogy it's like going from UNIX command line to windows. Worse yet, it's like setting up a network using command lines and file procedures versus the dreaded "wizzard" which never works.

My next plan is to go on with the led array using AVRDude and the Nerdkit method of making a hex file. Once the hex file is created I can load that using AVRStudio and the dragon. I have successfully uploaded hex files as such with the dragon before.

As for the bootloader, when I upload the hex files I see a mention of a bootloader in the log files, I thought AVR Studio uploaded a bootloader, I'll pay more attention to that.

The reason I'm using the studio is that I have multiple projects down the pike, friends of mine have been asking me to make some cool looking trinkets for them. I already made one for a friend using AVR Studio with no errors but I wrote the code from scratch. Just playing around with stuff right now but I see it's starting to get serious. This could be the next step in my career.

February 11, 2012
by Rick_S
Rick_S's Avatar

It's a career I wish I had taken when I was young. Instead I started an EET program and after a semester ran out of money and went into the work force instead. So now at age 46, I find myself a CNC Machine programmer by trade but have a strong tie hobby wise to electronics.

If you love it, don't let anything get in your way and pursue it. Most of all, have fun with it!!

Rick

Post a Reply

Please log in to post a reply.

Did you know that binary numbers use base 2 to represent numbers, and these are important for understanding microcontroller registers? Learn more...