1

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;
}
9
  • Have you compared this with the assembly generated by a C program? e.g. DDRB = 0xff;, while (1) PORTB = 0xff; Commented Jul 13, 2015 at 11:01
  • @BrettHale Yes, I have now also included the successfully compiled C program. Commented Jul 13, 2015 at 11:04
  • Those two programs aren't equivalent. The C version initializes PORTB to zero, while the assembly version doesn't. Commented Jul 13, 2015 at 11:06
  • 1
    Does the linker know anything about a global init symbol? Shouldn't you be making main global? Commented Jul 13, 2015 at 11:10
  • Good comment @BrettHale After rewriting the program a few times i totally forgot about it. Unfortunately, it did not solve my issue. Commented Jul 13, 2015 at 11:16

1 Answer 1

2

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.

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

Comments

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.