0

I've inherited a mildly-complicated C program for one of the AVR32 32 bit microprocessors.

However, I have no information about how to compile it. I've been trying to put together a make-file for it for a bit now, and have been having no success. Hopefully someone can tell me where I am going wrong.


Basically, I have a project structure that looks like this:

/
ControllerR3.c     # This is the main program file
    /FRAMEWORK
        /DRIVERS
            /ADC
                adc.c
                adc.h
            /GPIO
                gpio.c
                gpio.h
            {another 6 hardware drivers}
        /SERVICES
            /DELAY
                delay.c
                delay.h

Basically, ControllerR3.c includes adc.h, gpio.h, etc, and calls functions that are prototyped in those various header files. The actual functions in the various FRAMEWORK headers are actually defined in the .c files.

All the .h files are wrapped in include protections:

#ifndef _USART_H_
#define _USART_H_
{snip header file contents}
#endif  // _USART_H_

Now, as I understand it, I have to compile the various .c files into object (.o) files, and then call the linker to merge all the object files together in to the final executable (in this case, it's a .elf file).
As such, I have written a small makefile:

CC      = avr32-gcc

CFLAGS  = -mpart=uc3a0512 -O1 -ffunction-sections -masm-addr-pseudos -g3 -Wall -c -std=gnu99 
COMP_INC =  -I"./FRAMEWORK/UTILS" \
            -I"./FRAMEWORK/UTILS/PREPROCESSOR"

LIB_INC =   -I"./FRAMEWORK/UTILS/LIBS/NEWLIB_ADDONS/INCLUDE" \
            -I"./FRAMEWORK/SERVICES/DELAY" \
            -I"./FRAMEWORK/DRIVERS/USART" \
            -I"./FRAMEWORK/DRIVERS/TC" \
            -I"./FRAMEWORK/DRIVERS/SPI" \
            -I"./FRAMEWORK/DRIVERS/PWM" \
            -I"./FRAMEWORK/DRIVERS/PM" \
            -I"./FRAMEWORK/DRIVERS/INTC" \
            -I"./FRAMEWORK/DRIVERS/GPIO" \
            -I"./FRAMEWORK/DRIVERS/FLASHC" \
            -I"./FRAMEWORK/DRIVERS/CPU/CYCLE_COUNTER" \
            -I"./FRAMEWORK/BOARDS" \
            -I"./FRAMEWORK/DRIVERS/ADC" 

DRIVER_PATH = ./FRAMEWORK/DRIVERS



all: libraries main

main:
    $(CC) $(CFLAGS) $(COMP_INC) $(LIB_INC) -o"Debug/$@.o" "ControllerR3.c"
    $(CC) "Debug/adc.o" "Debug/flashc.o" "Debug/gpio.o" "Debug/intc.o" "Debug/pm.o" "Debug/pwm.o" "Debug/tc.o" "Debug/usart.o" "Debug/spi.o" "Debug/main.o" "Debug/delay.o" \
        -o Debug/CookerControlR3.elf

libraries: adc.c flashc.c gpio.c intc.c pm.c pwm.c spi.c tc.c usart.c delay.c


adc.c: 
    $(CC) $(CFLAGS) $(COMP_INC) -o"Debug/$*.o" "$(DRIVER_PATH)/ADC/$@"

flashc.c: 
    $(CC) $(CFLAGS) $(COMP_INC) -o"Debug/$*.o" "$(DRIVER_PATH)/FLASHC/$@"

gpio.c: 
    $(CC) $(CFLAGS) $(COMP_INC) -o"Debug/$*.o" "$(DRIVER_PATH)/GPIO/$@"

intc.c: 
    $(CC) $(CFLAGS) $(COMP_INC) -o"Debug/$*.o" "$(DRIVER_PATH)/INTC/$@"

pm.c: 
    $(CC) $(CFLAGS) $(COMP_INC) -o"Debug/$*.o" "$(DRIVER_PATH)/PM/$@"

pwm.c: 
    $(CC) $(CFLAGS) $(COMP_INC) -o"Debug/$*.o" "$(DRIVER_PATH)/PWM/$@"

spi.c: 
    $(CC) $(CFLAGS) $(COMP_INC) -o"Debug/$*.o" "$(DRIVER_PATH)/SPI/$@"

tc.c: 
    $(CC) $(CFLAGS) $(COMP_INC) -o"Debug/$*.o" "$(DRIVER_PATH)/TC/$@"

usart.c: 
    $(CC) $(CFLAGS) $(COMP_INC) -o"Debug/$*.o" "$(DRIVER_PATH)/USART/$@"


delay.c: 
    $(CC) $(CFLAGS) $(COMP_INC) -o"Debug/$*.o" -I"FRAMEWORK/DRIVERS/CPU/CYCLE_COUNTER" "FRAMEWORK/SERVICES/DELAY/$@"

This successfully builds all the various object files, and then fails at the linking stage with:

C:\[snip - private]/./FRAMEWORK/DRIVERS/GPIO/gpio.h:507: multiple definition of `gpio_local_clr_gpio_open_drain_pin'
Debug/gpio.o:C:\[snip - private]/./FRAMEWORK/DRIVERS/GPIO/gpio.h:507: first defined here
Debug/main.o: In function `gpio_local_tgl_gpio_open_drain_pin':
C:\[snip - private]/./FRAMEWORK/DRIVERS/GPIO/gpio.h:525: multiple definition of `gpio_local_tgl_gpio_open_drain_pin'
Debug/gpio.o:C:\[snip - private]/./FRAMEWORK/DRIVERS/GPIO/gpio.h:525: first defined here
Debug/main.o: In function `usart_reset_status':
C:\[snip - private]/./FRAMEWORK/DRIVERS/USART/usart.h:409: multiple definition of `usart_reset_status'
Debug/usart.o:C:\[snip - private]/./FRAMEWORK/DRIVERS/USART/usart.h:409: first defined here
Debug/main.o: In function `usart_parity_error':
[snip a hundred or so lines]

So obviously, I have a problem with multiple definitions.

At this point, I'm a bit over my head. I don't have much experience with C development, and just getting the makefile to the point where it is now took a lot of reading.

What is causing the multiple definition issues I have here? What changes do I need to make to the makefile to prevent this?

I know this project was built successfully in the past, as we have a hardware device that actually runs it. However, I need to make some changes, so just using the existing compiled version is no-longer acceptable.

The existing version was built by an external-contractor who is no-longer available, so I can't really ask them how they made it work.

Fake Name
  • 5,556
  • 5
  • 44
  • 66
  • Does you header files (especially `gpio.h usart.h` include the conditional macro like `#ifndef _GPIO_H #define _GPIO_H ... #endif` This will avoid multiple inclusion of header files and re-defining the macros. – Raj Sep 17 '12 at 13:00
  • @RajTendulkar - Yes, I have include protections. I noted this in my question. – Fake Name Sep 17 '12 at 14:33
  • Without source code, its a bit difficult to guess. However I think so that you are including gpio.h in your main.c file as well as that is being included in the file lets say gpio.c. So there is multiple definition of this function and then compiling for main, you are having this rule `$(CC) "Debug/adc.o" "Debug/flashc.o" "Debug/gpio.o" "Debug/intc.o" "Debug/pm.o" "Debug/pwm.o" "Debug/tc.o" "Debug/usart.o" "Debug/spi.o" "Debug/main.o" "Debug/delay.o" \ -o Debug/CookerControlR3.elf` Did you try removing Debug/gpio.o from this rule? Does it compile ? – Raj Sep 17 '12 at 14:41
  • @RajTendulkar - Removing the `.o` files that cause the duplicate definition errors just produce errors that the linker can't find the definition of a lot of *other* functions. I need the functions in the various libraries. – Fake Name Sep 17 '12 at 14:43
  • I mean, I have include protections - `#ifndef _USART_H_ #define _USART_H_ {snip header file contents} #endif // _USART_H_`, so it shouldn't be that. – Fake Name Sep 17 '12 at 14:43
  • FYI, it's not just `gpio.o`, it's all the libraries. I just didn't include all 100+ error lines, as they're all basically the same. – Fake Name Sep 17 '12 at 14:44
  • You can try another option, that you make all these functions as `static`. This should help to overcome the problem. – Raj Sep 17 '12 at 14:45
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/16783/discussion-between-raj-tendulkar-and-fake-name) – Raj Sep 17 '12 at 14:49

2 Answers2

1

It looks like you have a function implemented in your header files. When you compile object1 and object2 (say main.o and gpio.o) you have your code duplicated in both object, and those cannot be linked together.

In this situation typically I leave the declaration of the function in the header file and move its implementation in one of the object code (no matter which).

Can you confirm that at "gpio.h:507" you have the implementation and not only the signature of the function?

Jack
  • 1,488
  • 11
  • 21
  • Line 507 is: `extern __inline__ void gpio_local_clr_gpio_open_drain_pin(unsigned int pin) { AVR32_GPIO_LOCAL.port[pin >> 5].oders = 1 << (pin & 0x1F); } `, so it looks like you are correct. How the deuce did this *ever* work? – Fake Name Sep 17 '12 at 14:29
  • I can certainly move all the functions out of the file (`gpio.h`), but this file is part of the Atmel Software Framework (see [here](http://www.atmel.com/tools/AVRSOFTWAREFRAMEWORK.aspx)), so it should be possible to use it without modification. – Fake Name Sep 17 '12 at 14:32
  • Is there a `gcc` option that makes the linker ignore duplicate instances in situations where something is `__inlined__`? I'm looking through the eclipse project files to see if I can see anything. – Fake Name Sep 17 '12 at 14:38
  • No, it looks like eclipse just emits a makefile, and I can't see any information on what it would put there. – Fake Name Sep 17 '12 at 14:40
  • As far as I know, it's a compiler choice to produce inline code for a function marked with "inline" keyword. Of course, if compiler inlines the code, then the function really does not exist in the objects, and the linker can assemble together *.o with no problems. I suppose that the the code is compiler-dependent and not completely portable. If you can modify the code I suggest you to change "extern __inline__ void" with "#define" :) – Jack Sep 17 '12 at 14:48
  • Oh, I'm sure it's **horribly** compiler dependent. This is an embedded microprocessor after all (Atmel AVR). The issue is that these functions are in some of the standard libraries for this device, which means that if something is going wrong, it's pretty much definitely *my* fault. – Fake Name Sep 17 '12 at 14:54
  • Plus, I don't think the keyword _ _inline_ _ (with two underscores) is standard C (and not even "inline", which is c++); this could be enforce the idea that this is really compiler-dependent (or maybe it is #defined somewhere else?) – Jack Sep 17 '12 at 14:55
  • Also, leading the function is: `#if (defined __GNUC__) __attribute__((__always_inline__)) #endif`. It also supports several compilers (`gcc` and `IAR EWAVR32`). – Fake Name Sep 17 '12 at 15:09
  • the `__inline__` vs `inline` thing seems to be a gnu-c thing: http://gcc.gnu.org/onlinedocs/gcc/Alternate-Keywords.html#Alternate-Keywords – Fake Name Sep 17 '12 at 15:18
0

Well, it turned out I was using too recent an IDE.

I opened the project in the correct IDE (in this case, the older version of Atmel avr32 studio that's based on eclipse), and it somehow automagically deduced the structure, and put everything together correctly.

Anyways, while it's not so much that I solved the problem as avoided it, I'm marking this question as answered. I've already spent too much time trying to figure out what eclipse is doing.

Fake Name
  • 5,556
  • 5
  • 44
  • 66