0

I am trying to assemble (with avr-gcc) a program in ATMega328p that has an External Interrupt (in INT0 pin, to be precise).

But I am facing a big trouble when compiling that. The disassembled code does not load the interrupt vector table as it should.

The assembly code (for AVR):

.equ F_CPU, 16000000
.text
.global main
    .org 0x0000         ; changes interrupt vector table to INT0 ISR
    rjmp main           ; goto main     ---> ISR for main
    rjmp INT0_vect      ; goto EXT_INT0 ---> ISR for INT0 pin
INT0_vect:              ; IRQ0 Handler --> ISR code for INT0 pin
    ldi r16,0x20
    out PORTB,r16       ; turns led on
    reti                ; return from interrupt
.include "m328pdef.inc" ; main addresses in atmega328p
.include "wait.asm"     ; wait 1 second function delaration
main:                   ; interrupt setup (runs only once by reset)
    ldi r16,(1<<ISC01)|(1<<ISC00)   ; interrupts on rising edge of INT0
    sts EICRA,r16       ; setting the bits
    ldi r16,(1<<INT0)   ; Setting the interrupt request 0 to be enabled
    sts EIMSK,r16       ; Setting the interrupt request 0 to be enabled done
    sei                 ; enable global interrupts
loop:                   ; loop, main function repeats ...
    ldi r16,0x00
    out PORTB,r16       ; turns led off
    call wait           ; wait 1 second function
    rjmp loop

When disassemblying the binary, I get:

00000000 <__vectors>:
    0:  0c 94 34 00     jmp 0x68    ; 0x68 <__ctors_end>      ; RESET ISR SO FAR SO GOOD
    4:  0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>  ; INT0 ISR NOT POINTING TO 0x84 ADDRESS
    8:  0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
    c:  0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
    (...)

00000068 <__ctors_end>:
    68: 11 24           eor r1, r1
    (...)
    74: 0e 94 63 00     call    0xc6    ; 0xc6 <main>
    78: 0c 94 6f 00     jmp 0xde    ; 0xde <_exit>

0000007c <__bad_interrupt>:
    7c: 0c 94 00 00     jmp 0   ; 0x0 <__vectors>
    80: 22 c0           rjmp    .+68        ; 0xc6 <main>
    82: 00 c0           rjmp    .+0         ; 0x84 <INT0_vect>

00000084 <INT0_vect>:
    84: 00 e2           ldi r16, 0x20   ; 32
    86: 05 b9           out 0x05, r16   ; 5
    88: 18 95           reti

0000008a <wait>:
    (...)

000000de <_exit>:
    de: f8 94           cli

000000e0 <__stop_program>:
    e0: ff cf           rjmp    .-2         ; 0xe0 <__stop_program>

Expected disassembly:

00000000 <__vectors>:
    0:  0c 94 34 00     jmp 0x68    ; 0x68 <__ctors_end>      ; RESET ISR SO FAR SO GOOD
    4:  0c 94 XX 00     jmp 0x84    ; 0x84 <INT0_vect>        ; <--- Jump to INT0 ISR
    8:  0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
    c:  0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
    (...)

00000068 <__ctors_end>:
    68: 11 24           eor r1, r1
    (...)
    74: 0e 94 63 00     call    0xc6    ; 0xc6 <main>
    78: 0c 94 6f 00     jmp 0xde    ; 0xde <_exit>

(...)

00000084 <INT0_vect>:
    84: 00 e2           ldi r16, 0x20   ; 32
    86: 05 b9           out 0x05, r16   ; 5
    88: 18 95           reti

(...)

Makefile (compiling commands) is:

CC = avr-gcc
OBJ = avr-objcopy
DUMP = avr-objdump
SIZE = avr-size
MCU = -mmcu=atmega328
FLAGS = -c -x assembler-with-cpp
all:main.hex
main.hex:main.elf
    $(OBJ) -j .text -j .data -O ihex main.elf main.hex
main.elf:main.o
    $(CC) $(MCU) -o main.elf main.o
main.o:main.asm
    $(CC) $(MCU) -x assembler-with-cpp  -o main.o main.asm
clean:
    rm *.o *.elf *.hex main.txt
size:
    $(SIZE) -C --mcu=atmega328p main.elf
dump:
    $(DUMP) -d main.elf > main.txt
dump-all:
    $(DUMP) -j .data -j .text -D main.elf > main.txt

Is there anything I am missing?

8
  • I believe the toolchain will automatically pick up functions named __vector_# and put them into the table as appropriate. You do not need to set up the table yourself. Commented Oct 31, 2021 at 12:10
  • So how should I call the ISR in assembly code? Commented Nov 1, 2021 at 5:08
  • __vector_1 I think. Commented Nov 1, 2021 at 10:27
  • avr-ld is complaining the vector was already defined at crtatmega328p.o Commented Nov 2, 2021 at 17:18
  • 1
    If you don't need the C library use -nostdlib Commented Nov 2, 2021 at 17:19

1 Answer 1

1

I used avr-gcc -mmcu=atmega328 -nostdlib -x assembler-with-cpp -o main.elf main.asm instead of use avr-gcc to .asm->.o and then .o->.elf.

Thanks to Jester for the support!

Sign up to request clarification or add additional context in comments.

1 Comment

If you name the assembly source file with the standard file extension main.S, avr-gcc should pick up automatically that the assembly file is to be preprocessed with the C preprocessor, so the -x assembler-with-cpp is not necessary.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.