Compilation Failure, "Undefined Reference" ATmega-644p

Go To Last Post
10 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello guys,

It looks like there is some kind of compilation failure on my setup. It comes up with following build fail:sad

PS D:\Users\Arhitect\Documents\Project_Physalis\Physalis Software\version_1.0a> make flash
vr-gcc -Wl,-Map,version_1.0a.map -Wl,--gc-sections -mmcu=atmega644p fuse.o In_Lining_Functions.o main.o USART.o  -o version_1.0a.elf
ain.o: In function `main':
:\Users\Arhitect\Documents\Project_Physalis\Physalis Software\version_1.0a/main.c:38: undefined reference to `initTimer0'
:\Users\Arhitect\Documents\Project_Physalis\Physalis Software\version_1.0a/main.c:41: undefined reference to `initTimer1'
:\Users\Arhitect\Documents\Project_Physalis\Physalis Software\version_1.0a/main.c:82: undefined reference to `getDataADC_1'
ake: *** [version_1.0a.elf] Error 1
S D:\Users\Arhitect\Documents\Project_Physalis\Physalis Software\version_1.0a>

I looked up on the internet and it seems to me that there is a linker problem. I use makefile for this and honestly what is the linker missing i barely understand. Any input would be helpful

 

code is below:

 

>> In_Lining_Functions.h

/**********************************************************************************
**  Header File where [AVR's] hardware initialization functions are populated    **
**  ---------------------------------------------------------------------------- **
** -> Timer-0             -> External ADC Device No-1                            **
** -> Timer-1             -> USART-0                                             **
** -> System Interrupts                                                          **
** -> CPU clock/Speed                                                            **
**********************************************************************************/
#include <avr/io.h>
#include <Hardware_Connections_Bay.h>
//---------------------------- Hardware Initializations ------------------------ //

static inline void initTimer0(void);
/**\brief   initTimer0() Function sets-up the on-board Timer/Counter-0 for waveform
 *          generation. It is running in CTC mode with output on PB3 port/OC0A.
 *          The OC0A/PB3 toggles each time through generates 1.0 MHz clock signal
 *          on ADC [CLKIN] pin.
 *  \param  takes no parameters
 *  \param  takes no parameters
 *  \return nothing
 */

static inline void initTimer1(void);
/**\brief  initTimer1() Function sets-up 16-bit on-board Timer/Counter-1
 *         for normal mode operation, and is therefore used for timekeeping
 *         purposes. The clock prescaler is set to no-prescaling, full speed.
 * \param  accept no arguments
 * \param  accept no arguments
 * \return nothing
 */

static inline void getDataADC_1(void);
/**\brief   getDataADC() Function call uses [AVR's] 2 x PORTs E/H banks 2 x 8-Bits
 *          to read the 16-Bit data-bus from the AD-7723 external Analog-Digital-Converter.
 *          The 16-Bit value is then saved in variable.
 * \param   takes no argument
 * \param   takes no argument
 * \return  nothing, saves the value in ADC_data
 */

void secondsTick(void);
/**\brief   secondsTick() Function call increments the seconds creating timebase in seconds
 *          which then is compared with the Timer-1's overflows and a second is derived.
 *          This way the timebase of 60 seconds is implemented.
 * \param   takes no argument
 * \param   takes no argument
 * \return  nothing, increments seconds
 */
//---------------------------- Interrupt Service Routines ---------------------- //

ISR(TIMER1_OVF_vect);
/**< Timer-1 Overflow interrupt service routine to count amount of overflows for timebase */

>> In_Lining_Functions.c

 

#include <In_Lining_Functions.h>

uint8_t ADC_lowbyte, ADC_highbyte;
uint16_t ADC_data;
volatile uint16_t sys_tick;
volatile uint8_t seconds_;

//---------------------------- Interrupt Service Routines ---------------------- //
ISR(TIMER1_OVF_vect){

    sys_tick++;
}
//---------------------------- Hardware Initializations ------------------------ //

static inline void initTimer0(void){

    TCCR0A |= (1 << WGM01) | (1 << COM0A0); // toggle OCR0A on compare match
    TCCR0B |= (1 << CS00); // Timer-0/8 Bit in CTC mode and clock prescaler set div/1024
}

static inline void initTimer1(void){

    TCCR1B |= (1 << CS10); // timer clock prescaler at full speed no/prescaling
    TIMSK1 |= (1 << TOIE1); // timer overflow interrupt enabled
}

static inline void getDataADC_1(void){

    while((SAMPLE_ADC_CONTROL_PIN & (1 << DATA_READY_ADC)))
        { } // waiting time for DRDY to transition from HIGH >> LOW
    ADC_lowbyte = SAMPLE_ADC_LOW_PIN; // saves status of pins in BANK(A)in ADC_lowbyte variable
    ADC_highbyte = SAMPLE_ADC_HIGH_PIN; // saves status of pins in BANK(C)in ADC_highbyte variable
    ADC_data = ADC_lowbyte | (ADC_highbyte << 8); // Bitwise OR-ing to combine low-byte and high-byte
}

void secondsTick(void){

    seconds_++ ;
    if(seconds_ > 59){
        seconds_ = 0;
    }
}

>> main.c

 


//----------------- Preamble ----------------- //
#include <avr/io.h>
#include <USART.h>
#include <avr/power.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <In_Lining_Functions.h>
#include <Hardware_Connections_Bay.h>

#define OVERFLOWS_PER_SECOND  336 // 22 MHz/65535 ~ = 335.6984 overflows

uint8_t ADC_lowbyte, ADC_highbyte; // global variables which hold 16 bit DB(0-15) ADC data-bus
uint16_t ADC_data; // low and high bytes combined into one 16-bit word

volatile uint16_t sys_tick; // timebase implemented on Timer-1 overflows
volatile uint8_t seconds_;

//----------------- Initializations ----------------- //
int main (void){

    initUSART0(); // start USART-0
    printString("\nUSART-0 Hardware >>> initialized");
    printString("\r\n\n");
    initTimer0(); // start Timer-0
    printString("Timer-0 Hardware >>> initialized");
    printString("\r\n\n");
    initTimer1(); // start Timer-1
    printString("Timer-1 Hardware >>> initialized");
    printString("\r\n\n");
    _delay_ms(2000);
    printString("\r\n\n\n\n");
    printString("//---------------------=(                   )=--------------------//");
    printString("\r\n\n");
    //printString("|------------------------|\r\n");
    //printString("|       /         |      |\r\n");
    //printString("|    <>/<>_ __ _<>|<>    |\r\n");
    //printString("|     /    |      |  |   |\r\n");
    //printString("|  (o)     |(o)   | (o)  |\r\n");
    //printString("| (o)     (o)     | (o)  |\r\n");
    //printString("|        (o)      |      |\r\n");
    //printString("|               <>|<>    |\r\n");
    //printString("|               (o)(o)   |\r\n");
    //printString("|               (o)(o)   |\r\n");
    //printString("|                (o)     |\r\n");
    //printString("|                        |\r\n");
    //printString("|------------------------|\r\n\n");
    printString("//------------=(                                    )=---------//");
    printString("\r\n\n");
    printString("//--------------------=( Firmware version 1.0a )=-----------------//");
    printString("\r\n\n");
    printString("//-------------=( Compiled on: " __DATE__ " " __TIME__ " )=------------//");
    printString("\r\n\n");
    _delay_ms(2000);

    SAMPLE_ADC_CONTROL_DDR |= (1 << STATUS_LED); // LED setup for loop execution timing checks
    SAMPLE_ADC_CONTROL_DDR &= ~ (1 << DATA_READY_ADC); // DRDY data-ready/PB2 setup for input mode
    SAMPLE_ADC_CONTROL_DDR |= (1 << CLOCK_IN_ADC); // PB3/OC0A setup output mode for ADC clocking via Timer-0

    SAMPLE_ADC_LOW_DDR = 0x00; // ADC low byte data direction register setup in input mode BANK(A)
    SAMPLE_ADC_LOW_PORT = 0x00; // ADC Low byte port pull-up enabled, BANK(A)

    SAMPLE_ADC_HIGH_DDR = 0x00; // ADC high byte data direction register setup in input mode BANK(C)
    SAMPLE_ADC_HIGH_PORT = 0x00; // ADC high byte port pull-up enabled, BANK(C)
    OCR0A = 20; // Timer-0 output frequency  setup for ADC(CLKIN) pin ~ 150 KHz
    sei();
//----------------- Event loop ----------------- //
 while(1){// collects low and high bytes from ADC and combines them
          getDataADC_1();
          if(sys_tick == OVERFLOWS_PER_SECOND){
                sys_tick = 0;
               secondsTick();
               }
               SAMPLE_ADC_CONTROL_PORT ^= (1 << STATUS_LED); //loop execution time ~ 2.35 KHz
        }
 return(0);
}

FYI all files together with makefile are stored in one folder on the hard drive.

 

>> the makefile

 


##########------------------------------------------------------##########
##########              Project-specific Details                ##########
##########    Check these every time you start a new project    ##########
##########------------------------------------------------------##########

MCU   = atmega644p
F_CPU = 22000000UL
BAUD  = 115200UL
## Also try BAUD = 19200 or 38400 if you're feeling lucky.

## A directory for common include files and the simple USART library.
## If you move either the current folder or the Library folder, you'll
##  need to change this path to match.
LIBDIR = ../../AVR-Programming-Library

##########------------------------------------------------------##########
##########                 Programmer Defaults                  ##########
##########          Set up once, then forget about it           ##########
##########        (Can override.  See bottom of file.)          ##########
##########------------------------------------------------------##########

PROGRAMMER_TYPE = avrisp
# extra arguments to avrdude: baud rate, chip type, -F flag, etc.
PROGRAMMER_ARGS = -P com6 -b 19200

##########------------------------------------------------------##########
##########                  Program Locations                   ##########
##########     Won't need to change if they're in your PATH     ##########
##########------------------------------------------------------##########

CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
AVRSIZE = avr-size
AVRDUDE = avrdude

##########------------------------------------------------------##########
##########                   Makefile Magic!                    ##########
##########         Summary:                                     ##########
##########             We want a .hex file                      ##########
##########        Compile source files into .elf                ##########
##########        Convert .elf file into .hex                   ##########
##########        You shouldn't need to edit below.             ##########
##########------------------------------------------------------##########

## The name of your project (without the .c)
# TARGET = blinkLED
## Or name it automatically after the enclosing directory
TARGET = $(lastword $(subst /, ,$(CURDIR)))

# Object files: will find all .c/.h files in current directory
#  and in LIBDIR.  If you have any other (sub-)directories with code,
#  you can add them in to SOURCES below in the wildcard statement.
SOURCES=$(wildcard *.c $(LIBDIR)/*.c)
OBJECTS=$(SOURCES:.c=.o)
HEADERS=$(SOURCES:.c=.h)

## Compilation options, type man avr-gcc if you're curious.
CPPFLAGS = -DF_CPU=$(F_CPU) -DBAUD=$(BAUD) -I. -I$(LIBDIR)
CFLAGS = -Os -g -std=gnu99 -Wall
## Use short (8-bit) data types
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
## Splits up object files per function
CFLAGS += -ffunction-sections -fdata-sections
LDFLAGS = -Wl,-Map,$(TARGET).map
## Optional, but often ends up with smaller code
LDFLAGS += -Wl,--gc-sections
## Relax shrinks code even more, but makes disassembly messy
## LDFLAGS += -Wl,--relax
## LDFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm  ## for floating-point printf
## LDFLAGS += -Wl,-u,vfprintf -lprintf_min      ## for smaller printf
TARGET_ARCH = -mmcu=$(MCU)

## Explicit pattern rules:
##  To make .o files from .c files
%.o: %.c $(HEADERS) Makefile
	 $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<;

$(TARGET).elf: $(OBJECTS)
	$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LDLIBS) -o $@

%.hex: %.elf
	 $(OBJCOPY) -j .text -j .data -O ihex $< $@

%.eeprom: %.elf
	$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@

%.lst: %.elf
	$(OBJDUMP) -S $< > $@

## These targets don't have files named after them
.PHONY: all disassemble disasm eeprom size clean squeaky_clean flash fuses

all: $(TARGET).hex

debug:
	@echo
	@echo "Source files:"   $(SOURCES)
	@echo "MCU, F_CPU, BAUD:"  $(MCU), $(F_CPU), $(BAUD)
	@echo

# Optionally create listing file from .elf
# This creates approximate assembly-language equivalent of your code.
# Useful for debugging time-sensitive bits,
# or making sure the compiler does what you want.
disassemble: $(TARGET).lst

disasm: disassemble

# Optionally show how big the resulting program is
size:  $(TARGET).elf
	$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf

clean:
	rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \
	$(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \
	$(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \
	$(TARGET).eeprom

squeaky_clean:
	rm -f *.elf *.hex *.obj *.o *.d *.eep *.lst *.lss *.sym *.map *~ *.eeprom

##########------------------------------------------------------##########
##########              Programmer-specific details             ##########
##########           Flashing code to AVR using avrdude         ##########
##########------------------------------------------------------##########

flash: $(TARGET).hex
	$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<

## An alias
program: flash

flash_eeprom: $(TARGET).eeprom
	$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$<

avrdude_terminal:
	$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt

## If you've got multiple programmers that you use,
## you can define them here so that it's easy to switch.
## To invoke, use something like `make flash_arduinoISP`
flash_usbtiny: PROGRAMMER_TYPE = usbtiny
flash_usbtiny: PROGRAMMER_ARGS =  # USBTiny works with no further arguments
flash_usbtiny: flash

flash_usbasp: PROGRAMMER_TYPE = usbasp
flash_usbasp: PROGRAMMER_ARGS =  # USBasp works with no further arguments
flash_usbasp: flash

flash_arduinoISP: PROGRAMMER_TYPE = avrisp
flash_arduinoISP: PROGRAMMER_ARGS = -b 19200 -P /dev/ttyACM0
## (for windows) flash_arduinoISP: PROGRAMMER_ARGS = -b 19200 -P com5
flash_arduinoISP: flash

flash_109: PROGRAMMER_TYPE = avr109
flash_109: PROGRAMMER_ARGS = -b 9600 -P /dev/ttyUSB0
flash_109: flash

#flash_AVR_ISP_MK_II: PROGRAMMER_TYPE = avrisp_mk2
#flash_AVR_ISP_MK_II: PROGRAMMER_ARGS = -b 19200 -P USB

##########------------------------------------------------------##########
##########       Fuse settings and suitable defaults            ##########
##########------------------------------------------------------##########

## Mega 48, 88, 168, 328 default values
LFUSE = 0x62
HFUSE = 0xdf
EFUSE = 0x00

## Generic
FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m

fuses:
	$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) \
	           $(PROGRAMMER_ARGS) $(FUSE_STRING)
show_fuses:
	$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nv

## Called with no extra definitions, sets to defaults
set_default_fuses:  FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
set_default_fuses:  fuses

## Set the fuse byte for full-speed mode
## Note: can also be set in firmware for modern chips
set_fast_fuse: LFUSE = 0xE2
set_fast_fuse: FUSE_STRING = -U lfuse:w:$(LFUSE):m
set_fast_fuse: fuses

## Set the EESAVE fuse byte to preserve EEPROM across flashes
set_eeprom_save_fuse: HFUSE = 0xD7
set_eeprom_save_fuse: FUSE_STRING = -U hfuse:w:$(HFUSE):m
set_eeprom_save_fuse: fuses

## Clear the EESAVE fuse byte
clear_eeprom_save_fuse: FUSE_STRING = -U hfuse:w:$(HFUSE):m
clear_eeprom_save_fuse: fuses

 

This topic has a solution.

work in progress...

Last Edited: Thu. May 2, 2019 - 11:04 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dave_Zeb. wrote:
It looks like there is some kind of compilation failure on my setup.

Or just a straightforward syntax error?

We cannot see your project setup such that all the source files are shown.

 

Dave_Zeb. wrote:

:\Users\Arhitect\Documents\Project_Physalis\Physalis Software\version_1.0a/main.c:38: undefined reference to `initTimer0'
:\Users\Arhitect\Documents\Project_Physalis\Physalis Software\version_1.0a/main.c:41: undefined reference to `initTimer1'

And those functions are in the first source file you posted?  You have chosen to call these "static".  Will a static function name be "seen" outside of that compilation unit?

[wouldn't it be a bit easier if the toolchain would show what it determines lines 38 and 41 are?]

[sheesh -- or at least post the complete corresponding source file so that the counting can at least be close?!?]

[and if the answer is "I did!" then it isn't that source file that the compiler is seeing]

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Thu. May 2, 2019 - 12:54 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Try to  remove "static" from your function declarations in Inline_Functions.h and from your function definitions in Inline_Functions.c

 

 

 

Last Edited: Thu. May 2, 2019 - 01:16 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


 

 

removed "static" from both .h and .c files. The build fails with same error. Here us the project tree in "code blocks" IDE.

 

 

 

                                 

 

 

work in progress...

Last Edited: Thu. May 2, 2019 - 10:03 AM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You don't seem to understand "static" or "inline". Perhaps time to get a good book about learning C?

 

For the time being just remove "static" and "inline" all together. Your "inline_functions.h" (which is a misnomer as they are not inline!!) should be called something like support_fns.h and contain:

void initTimer0(void);
void initTimer1(void);
void getDataADC_1(void);
etc.

then the accompanying .c file would be:

 

void initTimer0(void) {
    //stuff
}
void initTimer1(void) {
    // stuff
}
void getDataADC_1(void) {
    // stuff
}
etc.

If you really have something that needs to be inlined then create ONLY a .h file for it and use:

__attribute__((always_inline)) static inline type name(type var, type var) {
    // stuff
}

Forget declarations for static inline functions - just use inlined definitions such as the above.

 

Last Edited: Thu. May 2, 2019 - 10:16 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

solved. thanks for the description. I was trying to figure out which version would be better for the setup, in terms of performance: is there any gain by in-lining these functions so that they are inserted all around places of invocation, or just declaring them without.

I have a "Programming in C", by Stephen Kochan, any other good reads?

work in progress...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm confused.  First there was "static" and compilation errors.  Then

Dave_Zeb. wrote:
removed "static" from both .h and .c files. The build fails with same error.

But now it is solved?  How?

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My further advice was to remove "inline" too which presumably solved it. You can't have code in a .h/.c file and have it "inline" at the same time.

 

I do wonder what the (over) attraction to "inline" is here anyway? What possible issue was it supposed to solve? As we all know (I think), "inline" is trading the saved speed of no CALL/RET for the potential bloat of multiply inserted code sequences. At best it should be used "sparingly".

 

If one is writing "library" code I would have thought the traditional .c/.h approach would be the usual choice.

 

(I may have to find a copy of "Programming in C" to find out what the attraction to "inline" is all about)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

as clawson wrote already, I removed the "static" from these .h  and.c files but leaving "inline" which was throwing same compiler build fail.

work in progress...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


clawson wrote:

(I may have to find a copy of "Programming in C" to find out what the attraction to "inline" is all about)

 

The only reference (3rd ed) to inline is...

 

 

 

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."