0

I have a problem with atmega32 as when i am using this code:

#include "../HAL/led/Led.h"
#define F_CPU 16000000UL
#include "../MCAL/Interrupt/ExtIntREG.h"
#include <avr/interrupt.h>

int flag = 0;
int main(void)
{ 
   SET_BIT(MCUCR, ISC00);
   SET_BIT(MCUCR, ISC01);
   SET_BIT(GICR, INT0);
   SET_BIT(SREG, I);
   Led_init(LED0);
   while(1)
   {
      Led_on(LED0);
   }
   
}
/*
ISR(INT0_vect)
{
   //flag = 1;
   Led_on(LED2);
}
*/

i use this to test the LED if it's working without working with the interrupt just testing the LED with including the avr/interrupt.h lib but the LED is not working unless i comment the including of the library.

Edit: when disabling the interrupts but still including the interrupt header still the led doesn't work.

and this is my make file:

DEVICE = atmega32
FILENAME = APP/main
FREQ = 16000000UL
COMPILE = avr-gcc -Wall -Os -mmcu=$(DEVICE)
ADDITIONAL = BIT_MATH.h REG.h STD.h
HELPERS = MCAL/DIO/Dio.c MCAL/DIO/Dio.h
BUZZER = HAL/buzzer/Buzzer.c HAL/buzzer/Buzzer.h HAL/buzzer/BuzzerCfg.h
LED = HAL/led/Led.h HAL/led/Led.c
PUSHBUTTON = HAL/push_button/PushButton.c HAL/push_button/PushButton.h HAL/push_button/PushButtonCfg.h
LCD = HAL/lcd/Lcd.c HAL/lcd/Lcd.h  HAL/lcd/LcdCfg.h
SSD = HAL/SSD/SSD.h HAL/SSD/SSDCfg.h HAL/SSD/SSD.c
INT = MCAL/Interrupt/ExtInt.c MCAL/Interrupt/ExtInt.h MCAL/Interrupt/ExtIntCfg.h MCAL/Interrupt/ExtIntREG.h
ADC = MCAL/ADC/ADC_CONFIG.h MCAL/ADC/ADC_INTERFACE.h MCAL/ADC/ADC_REG.h MCAL/ADC/ADC.c

defualt: compile upload

compile:
    $(COMPILE) $(FILENAME).c $(ADDITIONAL) $(INT) $(HELPERS) $(BUZZER) $(ADC) $(LED) $(SSD) $(PUSHBUTTON) $(LCD) -o $(FILENAME).o 
    $(COMPILE) -o $(FILENAME).elf $(FILENAME).o -nostartfiles
    avr-objcopy -j .text -j .data -O ihex $(FILENAME).elf $(FILENAME).hex
    avr-size --format=avr --mcu=$(DEVICE) $(FILENAME).elf 

upload:
    sudo avrdude -p m32 -c usbasp -e -U flash:w:$(FILENAME).hex -F -P usb
    
clean:
    rm $(FILENAME).o
    rm $(FILENAME).elf
    rm $(FILENAME).hex

when i don't use -nostartfiles this error apears

avr-gcc -Wall -Os -mmcu=atmega32 -o APP/main.elf APP/main.o APP/main.o: In function __vector_1': (.text+0x78): multiple definition of __bad_interrupt' /usr/lib/gcc/avr/5.4.0/../../../avr/lib/avr5/crtatmega32.o:(.text+0x0): first defined here APP/main.o: In function __vectors': (.text+0x0): multiple definition of __vectors' /usr/lib/gcc/avr/5.4.0/../../../avr/lib/avr5/crtatmega32.o:(.vectors+0x0): first defined here collect2: error: ld returned 1 exit status make: *** [makefile:19: compile] Error 1

  • 1
    "_the LED is not working_" What does this mean? What do you expect, and what do you get? Which LED, you have LED0 and LED2? – the busybee Aug 23 '22 at 06:58
  • 1
    Does the interrupt pin and LED pin map to the same harware I/O pin? – aulven Aug 23 '22 at 07:01
  • @thebusybee when I turn on the LED0 in the while loop without including the interrupt lib the LED0 is turning on normally, but when including the lib it's not turning on and don't worry about LED2 it's commented. – Ahmed Elsayed Aug 23 '22 at 15:13
  • @aulven no the LED is on a separate I/O pin – Ahmed Elsayed Aug 23 '22 at 15:14
  • 1
    You need to compare the map files of both variants, which the linker generates on request. I assume that including the interrupt header triggers the creation of an empty interrupt vector table, which jumps to reset for each uninitialized vector. And since you have enabled interrupts, this leads to a boot loop. Please check this and add your finding by [edit]ing your question. – the busybee Aug 23 '22 at 19:23
  • 1
    Oh, and please add your command lines to build the applications. – the busybee Aug 23 '22 at 20:31
  • @thebusybee when disabling the interrupts but still including the interrupt header still the led doesn't work. – Ahmed Elsayed Aug 23 '22 at 20:53
  • Did you compare the map files? What did you find? – the busybee Aug 24 '22 at 05:43
  • OT: Who wrote this makefile? It makes no usage of make's main purpose, to use a tree of dependencies to compile only changed sources. Currently it is not more than a bacth script. However, it works. ;-) – the busybee Aug 24 '22 at 05:45
  • OT: Why do you use `-nostartfiles`? Does any of the other modules provide the necessary startup code? – the busybee Aug 24 '22 at 05:46
  • 1
    Now, please use avr-objdump to generate disassemblies of both versions and compare them. I would use `avr-objdump -d APP/main.elf > any-name-you-see-fit.s` (and use different names for each version) and `diff name-for-version-with.s name-for-version-without.s`. You might want to add the output of diff to your question, I expect not too much, or at least the relevant parts. If you happen to use Windows, WinMerge is a known alternative, you can use Tools->Generate Patch to save a difference file. – the busybee Aug 24 '22 at 05:51
  • @thebusybee I generated the disassemblies for the file generated with ' -nostartfiles ' and when i try to compile without it it generates an error i edited the question with it and that's why i put it. – Ahmed Elsayed Aug 24 '22 at 18:44

1 Answers1

0

What you are doing:

In the first $(COMPILE) command, you are throwing a bunch of .c and .h files at the compiler:

$(COMPILE) <bunch-of-c-and-h-files> -o $(FILENAME).o

What avr-gcc does is to build an executable, statically linked ELF named APP/main.o. Despit its name, this is not what usually is referred to as "object file".

In the second command, you take that completely linked ELF file named APP/main.o and (try to) link it again:

$(COMPILE) -o $(FILENAME).elf $(FILENAME).o -nostartfiles

This means you are liking against all libraries and the startup code again. As you have already startup code (and thus vector table etc.) from the first complete link, you cannot link them again and consequently are getting errors thrown at you, and rightly so.

The usual layout of a Makefile is such that

  • The final .elf is generated by linking all object files (and libraries) together.

  • Each object file .o is compiled and assembled from a single source file aka. compilation unit .c, .cpp or .S and transformed using

    gcc -c module.c -o module.o <more options>
    

    where module.o in general depends on a bunch of header files, but you do not want to compile header files except you need pre-compiled headers.

GCC features automatic dependency generation to be used and included in Makefiles, but that's beyond the scope of this answer. Currently, you are mis-using Makefile like a shell script, which might be easier that grasping make's worflow and syntax.

As an aside, avrdude understands ELF, so no need to build Intex Hex file.

emacs drives me nuts
  • 2,785
  • 13
  • 23