Dear All,
While Programming the AVR Device (ATmega 328-PU), the AVRDUDE throws a compilation error. Please see below the exact error message in console.
D:\Users\Arhitect\Documents\C - Programs\AVR Projects__\Timer_Counter_learning_drills>make flash avr-gcc -Wl,-Map,Timer_Counter_learning_drills.map -Wl,--gc-sections -mmcu=atmega328p -o Timer_Counter_learning_drills.elf d:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/../../../../avr/lib/avr5/crtm328p.o:(.init9+0x0): undefined reference to `main' make: *** [Timer_Counter_learning_drills.elf] Error 1 D:\Users\Arhitect\Documents\C - Programs\AVR Projects__\Timer_Counter_learning_drills>make flash avr-gcc -Wl,-Map,Timer_Counter_learning_drills.map -Wl,--gc-sections -mmcu=atmega328p Functions_for_Project.o fuse.o main.o USART.o -o Timer_Counter_learning_drills.elf main.o: In function `main': D:\Users\Arhitect\Documents\C - Programs\AVR Projects__\Timer_Counter_learning_drills/main.c:22: undefined reference to `init_Timer_Counter_1' D:\Users\Arhitect\Documents\C - Programs\AVR Projects__\Timer_Counter_learning_drills/main.c:23: undefined reference to `init_Timer_Counter_0' make: *** [Timer_Counter_learning_drills.elf] Error 1 D:\Users\Arhitect\Documents\C - Programs\AVR Projects__\Timer_Counter_learning_drills>
That said, the two Timer/Counter-0/1 hardware peripherals are configured but in separate "Functions_for_Project.c" source file, and of course the function prototypes are declared in header file "Functions_Support.h" which is included in "main.c". Albeit all that cross-connections the compiler does not see that. So I thought, then the issue is with the linker aka "Makfiles". I open the Make File trying to see if I can add the mentioned source file >>"Functions_for_Project.c " as additional file to compiler together with the "main.c".
But because I barely understand what is what my efforts are bringing me to nowhere.
The suitable Make-File i use :
##########------------------------------------------------------########## ########## Project-specific Details ########## ########## Check these every time you start a new project ########## ##########------------------------------------------------------########## MCU = atmega328p F_CPU = 1000000UL 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 = -b 19200 -P com4 ##########------------------------------------------------------########## ########## 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 ##########------------------------------------------------------########## ########## 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
It would be of great appreciation if someone can give me an idea where and what exactly in make file I should change/edit to make this work. By the way the Program which is being programmed to AVR Device is below.
The Main:
#include <avr/io.h> #include <util/delay.h> #include <USART.h> #include <pinDefines.h> #include <Functions_Support.h> int main(void) { /*--------------------Initializations--------------------*/ LED_DDR=0xff; // LED's for output BUTTON_DDR=0x00; // button port as input BUTTON_PORT|=(1<<BUTTON);// activate pull-up for the port init_Timer_Counter_1(); // start timer 1 hardware init_Timer_Counter_0(); // start timer 0 hardware initUSART(); // start USART hardware printString("[AVR Device]>> active\r\n"); printString("[AVR Device]>> Hardware setup OK."); printString("\r\n"); /*--------------------Event loop--------------------*/ while(1){ printString("Timer/Counter-0 (value)= "); printByte(TCNT0); printString("\t"); printString("Timer/Counter-1 (value)= "); printWord(TCNT1); printString("\r"); } return(0); }
The "Functions_for_Project" source file:
#include <Functions_Support.h> #include <pinDefines.h> #include <util/delay.h> /** \Project specific functions and their calls, actual working functions their body, and type of arguments they requite. Function sys_Status() take no arguments and does not require anything. It turn 8 bit LED display on/off in various pattern, which can be used as we want. * * \no parameter * \no parameter * \return NOTHING * */ void sys_Status_(void) { uint8_t nju; for(nju=0; nju<9; nju++) { LED_PORT^=(1<<nju); _delay_ms(10); printString("tick - tack\r\n"); } for(nju=8; nju<255; nju--) { LED_PORT&=~(1>>nju); _delay_ms(10); printString("tic-tack-tock\r\n"); } } /** \brief Activates AVR's Timer/Counter-0 Hardware in "Normal-Mode" * * \param no parameters * \param no parameters * \return returns nothing, but one can access the TCNT0 Hardware Register anytime. * Function is used to activate internal hardware peripherals in default mode and make use of them in code. For timing events please use the following functions for convinience and less CPU overhead. */ static inline void init_Timer_Counter_0(void) { TCCR0B|=(1<<CS02)|(1<<CS00); // CLK/1024 (from prescaler), each tick is 1.024 millisecond. } /** \brief Activates AVR's Timer/Counter-1 Hardware in "Normal-Mode" * * \param no parameters * \param no parameters * \return returns nothing, but one can access the TCNT0 Hardware Register anytime. * Function is used to activate internal hardware peripherals in default mode and make use of them in code. For timing events please use the following functions for convenience and less CPU overhead. */ static inline void init_Timer_Counter_1(void) { TCCR1B|=(1<<CS12)|(1<<CS10); // CLK/1024 (from prescaler), each tick is 1.024 millisecond. } /** \brief makes use of the 16-Bit built-in Timer/Counter-1 Hardware to track the time * * \param takes no arguments * \param take no arguments * \return nothing * if show the passing of time in Normal-Mode of Operation which is just incrementing from 0-65535 and when if overflows, it rolls back to zero and starts again. Once can see the result on a 8 LED binary display attached to AVR. It uses Switch-Case construction */ void LED_time_Bar_Graph_0(void) { switch(TCNT1){ case 100 : LED_PORT=0b00000001; //printWord(TCNT1);printString("\r\n"); break; case 1000 : LED_PORT=0b00000011; //printWord(TCNT1);printString("\r\n"); break; case 5000 : LED_PORT=0b00000111; //printWord(TCNT1);printString("\r\n"); break; case 10000 : LED_PORT=0b00001111; //printWord(TCNT1);printString("\r\n"); break; case 15000 : LED_PORT=0b00011111; //printWord(TCNT1);printString("\r\n"); break; case 20000 : LED_PORT=0b00111111; //printWord(TCNT1);printString("\r\n"); break; case 30000 : LED_PORT=0b01111111; //printWord(TCNT1);printString("\r\n"); break; case 60000 : LED_PORT=0b11111111; //printWord(TCNT1);printString("\r\n"); break; default : LED_PORT=0b00000000; //printWord(TCNT1);printString("\r\n"); } } /** \brief makes use of the 16-Bit built-in Timer/Counter-1 Hardware to track the time * * \param takes no arguments * \param take no arguments * \return nothing * if show the passing of time in Normal-Mode of Operation which is just incrementing from 0-65535 and when if overflows, it rolls back to zero and starts again. Once can see the result on a 8 LED binary display attached to AVR. It uses if()-ELSE conditional construction. */ void LED_time_Bar_Graph_1(void) { if(TCNT1>100 && TCNT1<1000) { LED_PORT=0b00000011; //printWord(TCNT1);printString("\r\n"); } if(TCNT1>1000 && TCNT1<=5000) { LED_PORT=0b00001111; //printWord(TCNT1);printString("\r\n"); } if(TCNT1>5000 && TCNT1<=10000) { LED_PORT=0b00011111; //printWord(TCNT1);printString("\r\n"); } if(TCNT1>10000 && TCNT1<=15000) { LED_PORT=0b00111111; //printWord(TCNT1);printString("\r\n"); } if(TCNT1>15000 && TCNT1<=25000) { LED_PORT=0b01111111; //printWord(TCNT1);printString("\r\n"); } if(TCNT1>25000 && TCNT1<=50000) { LED_PORT=0b111111111; //printWord(TCNT1);printString("\r\n"); } }
The "Functions_Support.h" header file
/**< Support Functions that otherwise make the main code more readable */ #include <util/delay.h> #include <avr/io.h> #include <USART.h> void sys_Status_(void); static inline void init_Timer_Counter_0(void); static inline void init_Timer_Counter_1(void); void LED_time_Bar_Graph_0(void); void LED_time_Bar_Graph_1(void);
sorry for writing a long post.