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...
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.
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?
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.
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?
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
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
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!
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.
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.
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.