Forum: Mikrocontroller und Digitale Elektronik AVR führt Programm nicht aus, wenn zusätzliche Funktionen definiert sind


von Hauke (Gast)


Lesenswert?

Hallo,
ich bin Neuling was AVR-C und Mikrocontroller im Allgemeinen an geht und 
probiere gerade erste Sachen aus. Könnt ihr mir erklären, warum dieses 
Programm...
1
#define F_CPU 1000000UL
2
3
#include <avr/io.h>
4
#include <util/delay.h>
5
6
int main(void)
7
{
8
  DDRB |= (1 << PB4);
9
10
  while (1) {
11
    PORTB ^= (1 << PB4);
12
    _delay_ms(500);
13
  }
14
15
  return 0;
16
}

...ausgeführt wird (die LED blinkt), aber dieses:
1
#define F_CPU 1000000UL
2
3
#include <avr/io.h>
4
#include <util/delay.h>
5
6
int test(int i);
7
8
int main(void)
9
{
10
  DDRB |= (1 << PB4);
11
12
  while (1) {
13
    PORTB ^= (1 << PB4);
14
    _delay_ms(500);
15
  }
16
17
  return 0;
18
}
19
20
int test(int i)
21
{
22
  return 1;
23
}

...scheinbar nicht (LED bleibt aus)?

von Peter II (Gast)


Lesenswert?

was ist es denn für ein AVR?

von Hauke (Gast)


Lesenswert?

Ein ATtiny85... hätte ich vielleicht erwähnen sollen^^

von Stefan F. (Gast)


Lesenswert?

Sind das wirklich genau die beiden Programme, die du ausprobiert hast?

Oder hast du sie hier nur hin geschrieben, um deine Frage zu 
verdeutlichen, aber in Wirklichkeit ist das Programm komplexer?

Ich frage, weil ich an deinem zitierten Code keine Ursache für den 
Fehler sehen kann.

von Hauke (Gast)


Lesenswert?

Das ist exakt das, was ich mit avr-gcc übersetzt habe.

von Jim M. (turboj)


Lesenswert?

Ich sehe auf den ersten Blick keinen Grund. Sind die Compiler Warnungen 
an?
Fehler beim Flashen?

von Hauke (Gast)


Lesenswert?

Habe keine Fehler beim Flashen mit AVRISP mkII, sind die 
Compilerwarnungen standardmäßig an? Ich führe folgendes aus:
1
avr-gcc --mmcu=attiny85 -Os -c test.c -o test.o
2
avr-gcc test.o -o test.elf
3
avr-objcopy -O ihex -j .text -j.data test.elf test.hex
4
avrdude -p t85 -c avrispmkii -U flash:w:test.hex:a

Vielleicht liegt der Fehler auch darin. Danke schonmal für die schnellen 
Antworten bis jetzt!

von Walter S. (avatar)


Lesenswert?

am Programm liegt es nicht,
poste doch Mal alle Ausgaben die beim Compilieren, linken und flashen 
kommen

von Hauke (Gast)


Lesenswert?

Habe jetzt mal extra -v (verbose) angehängt:

http://hastebin.com/equveyitif.py

von Stefan F. (Gast)


Lesenswert?

Ich sehe da keinen Fehler. Hast du an dem Mikrocontroller einen 
Abblockkondensator? Und ist die Spannungsversorgung stabil genug?

von Hauke (Gast)


Lesenswert?

Ja, habe ich. Die Versorgungsspannung kommt aus einem L78S05, der ist 
auch mit Kondensatoren bestückt.

Mal davon abgesehen: Was spricht dafür, dass es an der Schaltung liegt? 
Die LED blinkt doch einwandfrei, wenn ich das erste Programm flashe.

Liegt es eventuell an meiner Toolchain? Ist es einen Versuch wert, diese 
selber nochmal zu kompilieren?

von ProjektX (Gast)


Lesenswert?

Am, zumindest uns gezeigten, Teil des Programms liegt es nicht. Deine 
int test(int i) - Funktion wird nicht in der main ausgeführt, somit wird 
diese wegoptimiert und übrig bleibt nur Teil, der auch dem ersten 
Programm entspricht.

Hast du zwischendurch die Optimierung ausgeschaltet o.ä.? Weil dann 
nämlich delay.h nicht mehr funktionieren würde.

Ansonsten fehlen weitere Informationen.

von Hauke (Gast)


Lesenswert?

Das Programm ist nur ein Test, dementsprechend wirklich vollständig 
oben abgebildet. Die Optimierung habe ich zumindest nicht bewusst 
ausgeschaltet, ich habe den Schalter -Os von avr-gcc verwendet.

Dass die Funktion test() nicht ausgeführt wird, ist Absicht. Du sprichst 
von "Wegoptimierung", das heißt der Compiler erkennt, dass die Funktion 
keine Referenz hat. Würde meine Toolchain richtig funktionieren, müsste 
der µC also exakt das gleiche Programm vorgesetzt bekommen.

Es liegt also mit hoher Wahrscheinlichkeit an GCC & Co, sehe ich das 
richtig?

von Stefan F. (Gast)


Lesenswert?

Erzeuge mal ein Assembler-Listing von beiden Varianten. Dann kannst du 
sie miteinander vergleichen und kontrolliere, um zu beurteilen, ob der 
Compiler fehlerhaft arbeitet.

objdump -h -S < test.elf

von Kugl (Gast)


Lesenswert?

Hauke schrieb:

> Es liegt also mit hoher Wahrscheinlichkeit an GCC & Co, sehe ich das
> richtig?

Nein.

Post doch bitte die zugehörigen lss-Dateien.

von Stefan F. (Gast)


Lesenswert?

Sorry, es muss "avr-objdump -h -S test.elf" heissen.

von Stefan F. (Gast)


Angehängte Dateien:

Lesenswert?

Mein Compiler erzeugt diesen Code für das erste Programm:
1
00000000 <main>:
2
   0:   bc 9a           sbi     0x17, 4 ; 23
3
   2:   90 e1           ldi     r25, 0x10       ; 16
4
   4:   88 b3           in      r24, 0x18       ; 24
5
   6:   89 27           eor     r24, r25
6
   8:   88 bb           out     0x18, r24       ; 24
7
   a:   2f e9           ldi     r18, 0x9F       ; 159
8
   c:   36 e8           ldi     r19, 0x86       ; 134
9
   e:   81 e0           ldi     r24, 0x01       ; 1
10
  10:   21 50           subi    r18, 0x01       ; 1
11
  12:   30 40           sbci    r19, 0x00       ; 0
12
  14:   80 40           sbci    r24, 0x00       ; 0
13
  16:   e1 f7           brne    .-8             ; 0x10 <__zero_reg__+0xf>
14
  18:   00 c0           rjmp    .+0             ; 0x1a <__zero_reg__+0x19>
15
  1a:   00 00           nop
16
  1c:   f3 cf           rjmp    .-26            ; 0x4 <__zero_reg__+0x3>

Und dieses für das zweite Programm:
1
00000000 <test>:
2
   0:   81 e0           ldi     r24, 0x01       ; 1
3
   2:   90 e0           ldi     r25, 0x00       ; 0
4
   4:   08 95           ret
5
6
00000006 <main>:
7
   6:   bc 9a           sbi     0x17, 4 ; 23
8
   8:   90 e1           ldi     r25, 0x10       ; 16
9
   a:   88 b3           in      r24, 0x18       ; 24
10
   c:   89 27           eor     r24, r25
11
   e:   88 bb           out     0x18, r24       ; 24
12
  10:   2f e9           ldi     r18, 0x9F       ; 159
13
  12:   36 e8           ldi     r19, 0x86       ; 134
14
  14:   81 e0           ldi     r24, 0x01       ; 1
15
  16:   21 50           subi    r18, 0x01       ; 1
16
  18:   30 40           sbci    r19, 0x00       ; 0
17
  1a:   80 40           sbci    r24, 0x00       ; 0
18
  1c:   e1 f7           brne    .-8             ; 0x16 <main+0x10>
19
  1e:   00 c0           rjmp    .+0             ; 0x20 <main+0x1a>
20
  20:   00 00           nop
21
  22:   f3 cf           rjmp    .-26            ; 0xa <main+0x4>

Beim Reset beginnt die Programmausführung an Adresse 0. Hier steht die 
Test-Funktion, die nach den beiden ldi Befehlen mit ret zurück kehrt. 
Und an dieser Stelle stürzt der µC ab,wiel die Funktion nicht mit call 
aufgerufen wurde.

Eigentlich hätte sie hinter <main> stehen müssen. Außerdem fehlt in 
beiden Fällen eine ganze Menge Code, nämlich die 
Initialisierungsroutinen der libc.

Wenn ich das längere Programm mit meinem erprobten Makefile compiliere, 
kommt was ganz anderes raus:
1
00000000 <__vectors>:
2
   0:  0e c0         rjmp  .+28       ; 0x1e <__ctors_end>
3
   2:  15 c0         rjmp  .+42       ; 0x2e <__bad_interrupt>
4
   4:  14 c0         rjmp  .+40       ; 0x2e <__bad_interrupt>
5
   6:  13 c0         rjmp  .+38       ; 0x2e <__bad_interrupt>
6
   8:  12 c0         rjmp  .+36       ; 0x2e <__bad_interrupt>
7
   a:  11 c0         rjmp  .+34       ; 0x2e <__bad_interrupt>
8
   c:  10 c0         rjmp  .+32       ; 0x2e <__bad_interrupt>
9
   e:  0f c0         rjmp  .+30       ; 0x2e <__bad_interrupt>
10
  10:  0e c0         rjmp  .+28       ; 0x2e <__bad_interrupt>
11
  12:  0d c0         rjmp  .+26       ; 0x2e <__bad_interrupt>
12
  14:  0c c0         rjmp  .+24       ; 0x2e <__bad_interrupt>
13
  16:  0b c0         rjmp  .+22       ; 0x2e <__bad_interrupt>
14
  18:  0a c0         rjmp  .+20       ; 0x2e <__bad_interrupt>
15
  1a:  09 c0         rjmp  .+18       ; 0x2e <__bad_interrupt>
16
  1c:  08 c0         rjmp  .+16       ; 0x2e <__bad_interrupt>
17
18
0000001e <__ctors_end>:
19
  1e:  11 24         eor  r1, r1
20
  20:  1f be         out  0x3f, r1  ; 63
21
  22:  cf e5         ldi  r28, 0x5F  ; 95
22
  24:  d2 e0         ldi  r29, 0x02  ; 2
23
  26:  de bf         out  0x3e, r29  ; 62
24
  28:  cd bf         out  0x3d, r28  ; 61
25
  2a:  02 d0         rcall  .+4        ; 0x30 <main>
26
  2c:  10 c0         rjmp  .+32       ; 0x4e <_exit>
27
28
0000002e <__bad_interrupt>:
29
  2e:  e8 cf         rjmp  .-48       ; 0x0 <__vectors>
30
31
00000030 <main>:
32
  30:  bc 9a         sbi  0x17, 4  ; 23
33
  32:  90 e1         ldi  r25, 0x10  ; 16
34
  34:  88 b3         in  r24, 0x18  ; 24
35
  36:  89 27         eor  r24, r25
36
  38:  88 bb         out  0x18, r24  ; 24
37
  3a:  2f e9         ldi  r18, 0x9F  ; 159
38
  3c:  36 e8         ldi  r19, 0x86  ; 134
39
  3e:  81 e0         ldi  r24, 0x01  ; 1
40
  40:  21 50         subi  r18, 0x01  ; 1
41
  42:  30 40         sbci  r19, 0x00  ; 0
42
  44:  80 40         sbci  r24, 0x00  ; 0
43
  46:  e1 f7         brne  .-8        ; 0x40 <__SREG__+0x1>
44
  48:  00 c0         rjmp  .+0        ; 0x4a <__SREG__+0xb>
45
  4a:  00 00         nop
46
  4c:  f3 cf         rjmp  .-26       ; 0x34 <main+0x4>
47
48
0000004e <_exit>:
49
  4e:  f8 94         cli
50
51
00000050 <__stop_program>:
52
  50:  ff cf         rjmp  .-2        ; 0x50 <__stop_program>

So sieht es aber richtig aus. Am Anfang ab Adresse 0 kommen die ganzen 
Interrupt-Vektoren, dann die Initialisierung (<__ctors_end>) und die 
springt zu <main>.

Mein Makefile führt folgenden Kommandos aus:

avr-gcc -c -Wall -O1 -fshort-enums -mmcu=attiny85 -DF_CPU=1000000 
-ffunction-sections -fdata-sections -std=c99   -o test2.o test2.c
avr-gcc -Wall -O1 -fshort-enums -mmcu=attiny85 -DF_CPU=1000000 
-ffunction-sections -fdata-sections -lm -Wl,--gc-sections -o test.elf 
test2.o
avr-objcopy -j .text -j .data -O ihex test.elf test.hex

von Stefan F. (Gast)


Lesenswert?

Die Fehlerursache ist, dass du beim zweiten gcc Aufruf den Parameter 
"-mmcu=attiny85" vergessen hast.

von Hauke (Gast)


Lesenswert?

DANKE VIELMALS!

Meine Güte, da hätte ich noch lange nach gesucht...

Also war ich mit meiner Vermutung ganz in der Nähe des Problems (hatte 
für mich selber nicht ausgeschlossen, dass ich avr-gcc falsch verwende). 
Ich merke schon, das Beste ist, ich befasse mich jetzt mit Assembler und 
wenn ich darin flüssig bin, steige ich wieder auf C um.

Danke an alle für die schnellen Antworten. Problem gelöst, PEBKAC!

von Stefan F. (Gast)


Lesenswert?

Ein bisschen Assembler Grundkenntnisse helfen in der Tat bei der 
Fehlersuche.

Hier kannst es spielerisch lernen: 
http://stefanfrings.de/avr_workshop/index.html

von Peter D. (peda)


Lesenswert?

Hauke schrieb:
> Ich merke schon, das Beste ist, ich befasse mich jetzt mit Assembler und
> wenn ich darin flüssig bin, steige ich wieder auf C um.

Es sollte schon reichen, wenn Du einfach die Meldungen des Compilers 
liest.
1
warning: #warning "device type not defined"

Profis nehmen den Schalter "-Werror", dann bricht der Compiler schon bei 
Warnungen ab.

: Bearbeitet durch User
von Possetitjel (Gast)


Lesenswert?

Peter D. schrieb:

> Es sollte schon reichen, wenn Du einfach die Meldungen
> des Compilers liest.
>
> warning: #warning "device type not defined"

Und wo genau im oben geposteten Compiler-Output finde ich
diese Zeile? Vielen Dank im Voraus.

von Peter D. (peda)


Lesenswert?

Ich hatte nur im Beitrag von Stefan Us gelesen, daß -mmcu fehlen soll.
Das gepostete Make ist ja von Stefan Us.
Dein Make hast Du nicht gezeigt.

Wenn ich -mmcu weglasse, kommt bei mir die Warnung im Consolenfenster.

: Bearbeitet durch User
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.