Forum: Mikrocontroller und Digitale Elektronik leere funktion in c code ändert verhalten (attiny13)


von monad (Gast)


Lesenswert?

Moin, ich versuche derzeit verzweifelt ein stück c code auf nem attiny13 
zum laufen zu bringen. Allerdings scheint eine leere c funktion dafür zu 
sorgen, dass der µkontroller nicht läuft:

funktionierender code:

#define F_CPU 9600000UL

#include <avr/io.h>
#include <util/delay.h>

/*
int blabb(){
    return 0;
}
*/


int main (void) {

    DDRB |= (1 << PB3);
    while(1) {
        PORTB ^= (1 << PB3);
        _delay_ms(5);
    }

    return 0;
}


sobald die leere funktion nicht mehr auskommentiert ist, hört PB3 auf zu 
toggeln. Kann das jemand erklären?
objdump der hex files:


/////////keine leere funktion
00000000 <.sec1>:
   0:  bb 9a         sbi  0x17, 3  ; 23
   2:  98 e0         ldi  r25, 0x08  ; 8
   4:  88 b3         in  r24, 0x18  ; 24
   6:  89 27         eor  r24, r25
   8:  88 bb         out  0x18, r24  ; 24
   a:  ef ed         ldi  r30, 0xDF  ; 223
   c:  fe e2         ldi  r31, 0x2E  ; 46
   e:  31 97         sbiw  r30, 0x01  ; 1
  10:  f1 f7         brne  .-4        ;  0xe
  12:  00 c0         rjmp  .+0        ;  0x14
  14:  00 00         nop
  16:  f6 cf         rjmp  .-20       ;  0x4


//////////leere funktion
00000000 <.sec1>:
   0:  80 e0         ldi  r24, 0x00  ; 0
   2:  90 e0         ldi  r25, 0x00  ; 0
   4:  08 95         ret
   6:  bb 9a         sbi  0x17, 3  ; 23
   8:  98 e0         ldi  r25, 0x08  ; 8
   a:  88 b3         in  r24, 0x18  ; 24
   c:  89 27         eor  r24, r25
   e:  88 bb         out  0x18, r24  ; 24
  10:  ef ed         ldi  r30, 0xDF  ; 223
  12:  fe e2         ldi  r31, 0x2E  ; 46
  14:  31 97         sbiw  r30, 0x01  ; 1
  16:  f1 f7         brne  .-4        ;  0x14
  18:  00 c0         rjmp  .+0        ;  0x1a
  1a:  00 00         nop
  1c:  f6 cf         rjmp  .-20       ;  0xa

von Peter II (Gast)


Lesenswert?

das stimmt etwas beim kompilieren nicht.

Am Anfang müsste die ISR-Vektoren kommen, die sehen ich bei dir nicht.

Wie erstellt du denn das Binary?

von monad (Gast)


Lesenswert?

Makefile:

CC=avr-gcc
CFLAGS=-mmcu=attiny13 -Os -c
LDFLAGS=
SOURCES=main.c
OBJECTS=$(SOURCES:.c=.o)
EXECUTABLE=progrm01.elf

all: $(SOURCES) $(EXECUTABLE)
  avr-objcopy -O ihex -j .text -j .data $(EXECUTABLE) 
$(EXECUTABLE:.elf=.hex)

$(EXECUTABLE): $(OBJECTS)
  $(CC) $(LDFLAGS) $(OBJECTS) -o $@

.cpp.o:
  $(CC) $(CFLAGS) $< -o $@

clean:
  rm $(OBJECTS)

von Rolf Magnus (Gast)


Lesenswert?

Deiner Ausgabe fehlt die Interrupt-Vektor-Tabelle. Normalerweise müsste 
bei 0 ein Sprung zum Startup-Code stehen, der dann mit main() weiter 
macht. Bei dir fängt's aber direkt mit der ersten Funktion an.

Zeig doch lieber mal den vom Compiler erzeugten Assembler-Code statt 
eines wieder disassemblierten Binaries. Das wäre etwas übersichtlicher.

von Peter II (Gast)


Lesenswert?

monad schrieb:
> Makefile:

bin mir nicht sicher, aber der linker muss auch wissen was es für ein µC 
ist. Das sehen ich bei dir nicht.

von Kurt (Gast)


Lesenswert?

> CFLAGS=-mmcu=attiny13 -Os -c

-Os  Keine Optimierung.

Die leere Funktion wird nicht entfernt.

von monad (Gast)


Lesenswert?

user@pc$ avr-objdump -h -S progrm01.elf

progrm01.elf:     file format elf32-avr

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         0000001e  00000000  00000000  00000074  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .data         00000000  00800060  0000001e  00000092  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  2 .comment      00000011  00000000  00000000  00000092  2**0
                  CONTENTS, READONLY

Disassembly of section .text:

00000000 <blabb>:
   0:  80 e0         ldi  r24, 0x00  ; 0
   2:  90 e0         ldi  r25, 0x00  ; 0
   4:  08 95         ret

00000006 <main>:
   6:  bb 9a         sbi  0x17, 3  ; 23
   8:  98 e0         ldi  r25, 0x08  ; 8
   a:  88 b3         in  r24, 0x18  ; 24
   c:  89 27         eor  r24, r25
   e:  88 bb         out  0x18, r24  ; 24
  10:  ef ed         ldi  r30, 0xDF  ; 223
  12:  fe e2         ldi  r31, 0x2E  ; 46
  14:  31 97         sbiw  r30, 0x01  ; 1
  16:  f1 f7         brne  .-4        ; 0x14 <main+0xe>
  18:  00 c0         rjmp  .+0        ; 0x1a <main+0x14>
  1a:  00 00         nop
  1c:  f6 cf         rjmp  .-20       ; 0xa <main+0x4>

von Kurt (Gast)


Lesenswert?

Peter II schrieb:
> monad schrieb:
>> Makefile:
>
> bin mir nicht sicher, aber der linker muss auch wissen was es für ein µC
> ist. Das sehen ich bei dir nicht.

CFLAGS=-mmcu=attiny13 -Os -c

von Peter II (Gast)


Lesenswert?

Kurt schrieb:
> -Os  Keine Optimierung.
>
> Die leere Funktion wird nicht entfernt.

und? Damit darf das Programm aber nicht fehlerhaft werden. Sein linker 
aufruf ist falsch.

von Peter II (Gast)


Lesenswert?

Kurt schrieb:
> Peter II schrieb:
>> monad schrieb:
>>> Makefile:
>>
>> bin mir nicht sicher, aber der linker muss auch wissen was es für ein µC
>> ist. Das sehen ich bei dir nicht.
>
> CFLAGS=-mmcu=attiny13 -Os -c

linker ist doch

$(EXECUTABLE): $(OBJECTS)
  $(CC) $(LDFLAGS) $(OBJECTS) -o $@

also LDFLAGS.

von Rolf Magnus (Gast)


Lesenswert?

Kurt schrieb:
>> CFLAGS=-mmcu=attiny13 -Os -c
>
> -Os  Keine Optimierung.

-Os steht für Größenoptimierung, nicht für keine Optimierung.

> Die leere Funktion wird nicht entfernt.

Kann sie auch gar nicht, da der Compiler nicht weiß, ob die Funktion von 
irgendwo anders aus aufgerufen wird. Wenn schon, müßte das der Linker 
tun.
Aber davon abgesehen: Ja, und? Auch wenn die Funktion nicht entfernt 
wird, sollte sie den Rest trotzdem nicht stören.

von monad (Gast)


Lesenswert?

vielen Dank, das war der Fehler. Musste natürlich
LDFLAGS=-mmcu=attiny13
setzen.

von S. R. (svenska)


Lesenswert?

Ich lege beim Linkeraufruf immer noch die CFLAGS dazu, weil das bei 
bestimmten Optimierungen (LTO) notwendig ist. Schaden tut es m.W. nie.

Die LFLAGS sind dann nur für den Linkeraufruf bestimmt.

von Patrick J. (ho-bit-hun-ter)


Lesenswert?

Ääääh ...

und jetzt ist der Code fehlerfrei?
Oder funktioniert der Code 'nur', wie man sich das vorgestellt hat, da 
die leere Funktion weg-optimiert wurde?

Tip:
Pack die unschöne Funktion ans Ende, dann kann Die auch drin bleiben 
ohne zu stören - braucht dann aber halt trotzdem Speicher.

Würde das wohl .elf File beim Assembler mit dem .lst File gleichsetzen 
...

Dann sieht man, daß MIT der Funktion, daß dort ein RET an 3.ter stelle 
steht.
(Wie der Compiler auf r24 und r25 kommt ... kA)

Da zuvor aber nicht bestimmt zur main gesprungen wird, beginnt der µC 
bei 0 mit dem Programm - und da kommt nach 3 Befehlen das 'ret' und ein 
Stapel-Überlauf nimmt seinen Lauf - durch das Return wird die 
Rücksprung-Adresse vom Stapel runter geholt, was hier wohl dann 0x80e0 
oder 0xe080 als Ziel ergeben wird - und da steht dann auch nur Müll, was 
dann nicht ganz der erwarteten Funktion des Programm entsprechen könnte.

MfG

von Peter II (Gast)


Lesenswert?

Patrick J. schrieb:
> Ääääh ...
>
> und jetzt ist der Code fehlerfrei?

ja, warum denn nicht?

Wenn er dem linker nicht die cpu übergibt, dann kann er den STartcode 
nicht einfügen, deswegen sieht der code so merkwürdig aus.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.