Philipp Braun
Philipp Braun

Reputation: 1573

Compiling an Assembly Program using avr-gcc

I am trying to compile a simple Assembly Program with avr-gcc to run on an Attiny85. Unfortunately, the program simply doesn't work. And I get no errors while uploading and compiling. I know that the program itself should work because it works using C. So what am I missing?

Compiling and Uploading:

avr-gcc blinky.S -mmcu=attiny85 -Os -g -o blinky.out
avr-objcopy -O ihex blinky.out blinky.hex
sudo avrdude -p attiny85 -c usbasp -P usb -e -U flash:w:blinky.hex

blinky.S

#define F_CPU 1000000L
#include <avr/io.h>

        .section text
        .org 0
        .global init

        rjmp init

init:
        ldi r23,0x00
        ldi r24,0xFF
        out _SFR_IO_ADDR(DDRB), r24
        out _SFR_IO_ADDR(PORTB), r23

        rjmp main

        .org 0x020
        .global main
main:
        out _SFR_IO_ADDR(PORTB), r24
        rjmp main

Output:

Philipps-MacBook-Pro:Desktop philippbraun$ sh script.sh attiny85 blinky.S

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e930b
avrdude: erasing chip

avrdude: safemode: Fuses OK

avrdude done.  Thank you.

COMPILING AS ASSEMBLY FILE

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e930b
avrdude: erasing chip
avrdude: reading input file "blinky.hex"
avrdude: input file blinky.hex auto detected as Intel Hex
avrdude: writing flash (46 bytes):

Writing | ################################################## | 100% 0.03s



avrdude: 46 bytes of flash written
avrdude: verifying flash memory against blinky.hex:
avrdude: load data flash data from input file blinky.hex:
avrdude: input file blinky.hex auto detected as Intel Hex
avrdude: input file blinky.hex contains 46 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.03s



avrdude: verifying ...
avrdude: 46 bytes of flash verified

avrdude: safemode: Fuses OK

avrdude done.  Thank you.

The following C program compiles successfully!

#define F_CPU 1000000L
#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
DDRB = 0xFF; // PORTB is output, all pins
PORTB = 0x00; // Make pins low to start

for (;;) {
PORTB = 0xFF; // invert all the pins
//_delay_ms(5000); // wait some time
}
return 0;
}

Upvotes: 1

Views: 5807

Answers (1)

Klaus
Klaus

Reputation: 25593

First I am wondering that you can assembly with your command line! For me it simply doesn't work!

So what you want to achieve? Compile with stdlib support ( irq jump table, jump to main at start? Or do you want to do it all by hand?

Do it all by hand:

avr-gcc -xassembler-with-cpp x.s -mmcu=attiny85 -nostdlib

use stdlib to get jump table:

avr-gcc -xassembler-with-cpp x.s -mmcu=attiny85

If you use it without jump table you should use avr-as instead of avr-gcc!

So I tried your code with the hand crafted version and my assembly was simply empty! Why?

You have a typo:

.section text

is wrong!

Use:

.section .text

My dump looks like that:

00000000 <init>:
   0:   8f ef           ldi r24, 0xFF   ; 255
   2:   87 bb           out 0x17, r24   ; 23
   4:   0d c0           rjmp    .+26        ; 0x20 <main>
...

00000020 <main>:
  20:   88 bb           out 0x18, r24   ; 24
  22:   fe cf           rjmp    .-4         ; 0x20 <main>

Nothing blinks here!

Next: Why use .org here? If you add something to init which is larger then 0x020 in code size it will be overridden by main! So simply remove that dirty lines!

#include <avr/io.h>

    ldi r23,0x00
    ldi r24,0xFF
    out _SFR_IO_ADDR(DDRB), r24

main:
    out _SFR_IO_ADDR(PORTB), r24
    out _SFR_IO_ADDR(PORTB), r23
    rjmp main

Results in:

00000000 <__ctors_end>:
   0:   70 e0           ldi r23, 0x00   ; 0
   2:   8f ef           ldi r24, 0xFF   ; 255
   4:   87 bb           out 0x17, r24   ; 23

00000006 <main>:
   6:   88 bb           out 0x18, r24   ; 24
   8:   78 bb           out 0x18, r23   ; 24
   a:   fd cf           rjmp    .-6         ; 0x6 <main>

And why you have used .global ? nobody references externally on your defined symbols init and main.

So if you use a version with stdlib, you only have to export main to make it visible by the start up code. But if you want to do that, there is no way to use init before main. As I know the avr-libc has no idea about an extra user init method at all.

Upvotes: 2

Related Questions