Habe die Frage hier schon einmal gestellt, aber leider keine Antwort
erhalten. Darum stelle ich sie hier noch einmal, etwas anders
formuliert. Vielleicht findet ja jemand noch eine Lösung.
Also, ich habe ein Programm (war einmal ne ganze Menge, mittlerweile
besteht es nur noch aus LEDs die ein und ausgeschaltet werden).
1
#define F_CPU 16000000UL
2
3
#include <avr/io.h>
4
#include <stdio.h>
5
#include <util/delay.h>
6
7
int main(void){
8
uint16_t i = 0;
9
DDRD = 0xff;
10
PORTD = 0x00;
11
uint8_t stat = 0;
12
while(1){
13
i = 0;
14
while(i <= 100){
15
_delay_ms(10);
16
i++;
17
}
18
if(stat == 1){
19
PORTD = 0xff;
20
stat = 0;
21
}
22
else{
23
PORTD = 0x00;
24
stat = 1;
25
}
26
}
27
return 0;
28
}
Läuft auch alles wunderbar. Die LEDs blinken im passenden Takt (etwa 1
Sekunde bei 16MHz) und alles ist toll.
Nun kompiliere ich noch ein paar mehr Quellen ein. Diese sind noch nicht
weiter per include eingebunden. Ich nutze alse den gleichen Code. Nun
blinkt aber nichts mehr. Ich habe keine Ahnung warum. Die beiden
kompilierten HEX-Files sehen am Anfang fast identisch aus, das mit dem
zusätzlichen Code kompilierte nur halt länger. Im AVRSimulator läuft das
ganze auch wunderbar durch.
Hat noch jemand eine Idee, was ich testen könnte? Mir würden evtl auch
Ansätze oder Ahnung schon weiterhelfen. Nur derzeit habe ich mich echt
komplett festgerannt.
Aso, der zusätzliche Code ist der UIP-Stack von A.Dunkels. Da ist nichts
AVR-lastiges dabei.
Hier noch der Link auf mein altes Posting, vllt hilft das ja jemandem:
Beitrag "uIP auf einem Atmega"
Gruß
Schmidti
Michael W. schrieb:
> Das Programm startet immer wieder neu. Nach der Initialisierung fehlt> ein while (1) also die Endlosschleife um das Hauptprogramm.
Die while-Schleife ist schon okay! Was genau meinst Du?
Nico ... schrieb:
>> Das Programm startet immer wieder neu. Nach der Initialisierung fehlt>> ein while (1) also die Endlosschleife um das Hauptprogramm.>> Die while-Schleife ist schon okay! Was genau meinst Du?
Da es keine while(1)-Schleife in dem Programm gibt, kann sie auch nicht
"schon okay" sein. Es wäre also gut, wenn Du die Frage neu formulierst.
Nico ... schrieb:
> Wie sieht der Code aus den Du noch hinzu fügst?
uip-Stack, ist eine ganze Menge.
http://www.sics.se/~adam/uip/index.php/Main_Page
Aber ist halt ersteinmal nicht für den AVR. Und es gibt keine
Fehlermeldung.
> Passt das ganze überhaupt noch in Deinen AVR? Optimierung eigeschaltet?
jup, brauche 20kb von 64
> Das Programm startet immer wieder neu. Nach der Initialisierung fehlt> ein while (1) also die Endlosschleife um das Hauptprogramm.
Nö, ist oben nur ungeschickt formatiert. Das while(1) ist da und, wenn
ich das HEX durch den Avrsimulator jage, sitzt er auch schon an der
Stelle und schaltet die Ports ein und aus. Auch mit dem uip-Stack
Gruß
Grrrr schrieb:
> Nico ... schrieb:>>> Das Programm startet immer wieder neu. Nach der Initialisierung fehlt>>> ein while (1) also die Endlosschleife um das Hauptprogramm.>>>> Die while-Schleife ist schon okay! Was genau meinst Du?>> Da es keine while(1)-Schleife in dem Programm gibt, kann sie auch nicht> "schon okay" sein. Es wäre also gut, wenn Du die Frage neu formulierst.
Und was ist das dann vor dem Pfeil???
Grrrr schrieb:
> Ooops.
Kann ja passieren. Und wüsste ich, wie ich hier solch schicken bunten
Code einfügen kann, hättest du das sicher auch sehen können. Aber leider
liegt es nicht daran. So ein Fehler hätte ich wohl spätestens auch dann
gefunden, wenn ich hier die Forensuche bemüht hätte.
Aber - wie schon erwähnt, der Code, so wie er oben steht, macht ja das
was er soll - nur wenn ich da was dazukompiliere nicht mehr.
Meine Vermutung geht nun dahin, dass der uip irgendwas an irgendeinem
Timer pfuscht, aber da ich ncihts davon aufrufe - und auch darin
eigentlich nichts passendes zu finden ist, weiß ich leider nicht weiter.
Gruß
schmidti schrieb:
> Kann ja passieren. Und wüsste ich, wie ich hier solch schicken bunten> Code einfügen kann, hättest du das sicher auch sehen können.
Vernünftige Formatierung hätte es auch getan :-)
> Meine Vermutung geht nun dahin, dass der uip irgendwas an irgendeinem> Timer pfuscht, aber da ich ncihts davon aufrufe
Eine Funktion die du nicht aufrufst, kann dir auch nicht ins Handwerk
pfuschen.
Wie compilierst du denn den uiP-Stack mit ein?
(AVR-Studio Projekt; makefile?)
Karl heinz Buchegger schrieb:
> Eine Funktion die du nicht aufrufst, kann dir auch nicht ins Handwerk> pfuschen.
Aber vielleicht werden irgendwelche Register gesetzt.
>> Wie compilierst du denn den uiP-Stack mit ein?> (AVR-Studio Projekt; makefile?)
Genaugenommen nutze ich Code::Blocks, habe nur AvrStudio einmal
getestet, da mir der Simulator gefällt, aber auch das ganze als
AVR-Studio-projekt und dann kompiliert läuft nicht.
So kompiliere ich nun meist aus Code::Blocks heraus. Alle benötigten
Dateien sind eingefügt. Als Optimierung noch -0s.
Gruß
Hallo,
ich mal wieder, habe noch ein wenig an dem Code herumgespielt und habe
den Spaß nach dem Kompilieren mal disassembliert. Und siehe da. Der Code
ist fast der gleiche, nur ein paar Register werden anders gesetzt.
Das komplett kompilierte Programm
1
netio.hex: file format ihex
2
3
Disassembly of section .sec1:
4
5
00000000 <.sec1>:
6
0: 0c 94 2a 00 jmp 0x54 ; 0x54
7
4: 0c 94 47 00 jmp 0x8e ; 0x8e
8
8: 0c 94 47 00 jmp 0x8e ; 0x8e
9
c: 0c 94 47 00 jmp 0x8e ; 0x8e
10
10: 0c 94 47 00 jmp 0x8e ; 0x8e
11
14: 0c 94 47 00 jmp 0x8e ; 0x8e
12
18: 0c 94 47 00 jmp 0x8e ; 0x8e
13
1c: 0c 94 47 00 jmp 0x8e ; 0x8e
14
20: 0c 94 47 00 jmp 0x8e ; 0x8e
15
24: 0c 94 47 00 jmp 0x8e ; 0x8e
16
28: 0c 94 47 00 jmp 0x8e ; 0x8e
17
2c: 0c 94 47 00 jmp 0x8e ; 0x8e
18
30: 0c 94 47 00 jmp 0x8e ; 0x8e
19
34: 0c 94 47 00 jmp 0x8e ; 0x8e
20
38: 0c 94 47 00 jmp 0x8e ; 0x8e
21
3c: 0c 94 47 00 jmp 0x8e ; 0x8e
22
40: 0c 94 47 00 jmp 0x8e ; 0x8e
23
44: 0c 94 47 00 jmp 0x8e ; 0x8e
24
48: 0c 94 47 00 jmp 0x8e ; 0x8e
25
4c: 0c 94 47 00 jmp 0x8e ; 0x8e
26
50: 0c 94 47 00 jmp 0x8e ; 0x8e
27
54: 11 24 eor r1, r1
28
56: 1f be out 0x3f, r1 ; 63
29
58: cf e5 ldi r28, 0x5F ; 95
30
5a: d8 e0 ldi r29, 0x08 ; 8
31
5c: de bf out 0x3e, r29 ; 62
32
5e: cd bf out 0x3d, r28 ; 61
33
60: 19 e1 ldi r17, 0x19 ; 25
34
62: a0 e6 ldi r26, 0x60 ; 96
35
64: b0 e0 ldi r27, 0x00 ; 0
36
66: ea e2 ldi r30, 0x2A ; 42
37
68: f4 e3 ldi r31, 0x34 ; 52
38
6a: 02 c0 rjmp .+4 ; 0x70
39
6c: 05 90 lpm r0, Z+
40
6e: 0d 92 st X+, r0
41
70: ac 3e cpi r26, 0xEC ; 236
42
72: b1 07 cpc r27, r17
43
74: d9 f7 brne .-10 ; 0x6c
44
76: 15 e3 ldi r17, 0x35 ; 53
45
78: ac ee ldi r26, 0xEC ; 236
46
7a: b9 e1 ldi r27, 0x19 ; 25
47
7c: 01 c0 rjmp .+2 ; 0x80
48
7e: 1d 92 st X+, r1
49
80: a6 36 cpi r26, 0x66 ; 102
50
82: b1 07 cpc r27, r17
51
84: e1 f7 brne .-8 ; 0x7e
52
86: 0e 94 49 00 call 0x92 ; 0x92
53
8a: 0c 94 13 1a jmp 0x3426 ; 0x3426
54
8e: 0c 94 00 00 jmp 0 ; 0x0
55
92: 8f ef ldi r24, 0xFF ; 255
56
94: 81 b9 out 0x01, r24 ; 1
57
96: 82 b9 out 0x02, r24 ; 2
58
98: 80 e0 ldi r24, 0x00 ; 0
59
9a: 90 e0 ldi r25, 0x00 ; 0
60
9c: 08 95 ret
61
9e: 08 95 ret
62
a0: 80 e0 ldi r24, 0x00 ; 0
63
a2: 90 e0 ldi r25, 0x00 ; 0
das funktionierende Programm, welches nur LEDs ein-/ausschaltet
1
netio_klein.hex: file format ihex
2
3
Disassembly of section .sec1:
4
5
00000000 <.sec1>:
6
0: 0c 94 2a 00 jmp 0x54 ; 0x54
7
4: 0c 94 47 00 jmp 0x8e ; 0x8e
8
8: 0c 94 47 00 jmp 0x8e ; 0x8e
9
c: 0c 94 47 00 jmp 0x8e ; 0x8e
10
10: 0c 94 47 00 jmp 0x8e ; 0x8e
11
14: 0c 94 47 00 jmp 0x8e ; 0x8e
12
18: 0c 94 47 00 jmp 0x8e ; 0x8e
13
1c: 0c 94 47 00 jmp 0x8e ; 0x8e
14
20: 0c 94 47 00 jmp 0x8e ; 0x8e
15
24: 0c 94 47 00 jmp 0x8e ; 0x8e
16
28: 0c 94 47 00 jmp 0x8e ; 0x8e
17
2c: 0c 94 47 00 jmp 0x8e ; 0x8e
18
30: 0c 94 47 00 jmp 0x8e ; 0x8e
19
34: 0c 94 47 00 jmp 0x8e ; 0x8e
20
38: 0c 94 47 00 jmp 0x8e ; 0x8e
21
3c: 0c 94 47 00 jmp 0x8e ; 0x8e
22
40: 0c 94 47 00 jmp 0x8e ; 0x8e
23
44: 0c 94 47 00 jmp 0x8e ; 0x8e
24
48: 0c 94 47 00 jmp 0x8e ; 0x8e
25
4c: 0c 94 47 00 jmp 0x8e ; 0x8e
26
50: 0c 94 47 00 jmp 0x8e ; 0x8e
27
54: 11 24 eor r1, r1
28
56: 1f be out 0x3f, r1 ; 63
29
58: cf e5 ldi r28, 0x5F ; 95
30
5a: d8 e0 ldi r29, 0x08 ; 8
31
5c: de bf out 0x3e, r29 ; 62
32
5e: cd bf out 0x3d, r28 ; 61
33
60: 10 e0 ldi r17, 0x00 ; 0
34
62: a0 e6 ldi r26, 0x60 ; 96
35
64: b0 e0 ldi r27, 0x00 ; 0
36
66: e2 ea ldi r30, 0xA2 ; 162
37
68: f0 e0 ldi r31, 0x00 ; 0
38
6a: 02 c0 rjmp .+4 ; 0x70
39
6c: 05 90 lpm r0, Z+
40
6e: 0d 92 st X+, r0
41
70: a0 36 cpi r26, 0x60 ; 96
42
72: b1 07 cpc r27, r17
43
74: d9 f7 brne .-10 ; 0x6c
44
76: 10 e0 ldi r17, 0x00 ; 0
45
78: a0 e6 ldi r26, 0x60 ; 96
46
7a: b0 e0 ldi r27, 0x00 ; 0
47
7c: 01 c0 rjmp .+2 ; 0x80
48
7e: 1d 92 st X+, r1
49
80: a0 36 cpi r26, 0x60 ; 96
50
82: b1 07 cpc r27, r17
51
84: e1 f7 brne .-8 ; 0x7e
52
86: 0e 94 49 00 call 0x92 ; 0x92
53
8a: 0c 94 4f 00 jmp 0x9e ; 0x9e
54
8e: 0c 94 00 00 jmp 0 ; 0x0
55
92: 8f ef ldi r24, 0xFF ; 255
56
94: 81 b9 out 0x01, r24 ; 1
57
96: 82 b9 out 0x02, r24 ; 2
58
98: 80 e0 ldi r24, 0x00 ; 0
59
9a: 90 e0 ldi r25, 0x00 ; 0
60
9c: 08 95 ret
61
9e: f8 94 cli
62
a0: ff cf rjmp .-2 ; 0xa0
Interessant sind dabei nun die Zeilen 0x60, 0x66, 0x68, 0x70, 0x76,
0x78, 0x7a, 0x80, 0x8a
Diese sind unterschiedlich. Dort werden irgendwelche Register gesetzt.
Einmal meist mit 0. Und einmal mit irgendwelche Werten. Woher kommen
die?
Das sind doch einfach nur die Arbeitsregister, oder?
Gruß
Was ich vergaß dazu zu sagen, wenn ich die Register mit den Werten aus
dem laufenden Programm fülle, dann geht auch das andere Programm. Also
muss ich nun nur noch heruasfinden, wieso diese Register so gesetzt
werden.
Hat noch jemand eine Idee?
Interessant sind wohl diese Zeilen, mir ist leider nur nicht ganz klar,
was die machen.
1
7e: 1d 92 st X+, r1
2
80: a6 36 cpi r26, 0x66 ; 102
3
82: b1 07 cpc r27, r17
4
84: e1 f7 brne .-8 ; 0x7e
Also - wenn ich das recht verstehe schreibt er den Inhalt von r1 in die
Adresse von X, erhöht das X um 1 und vergleich dann X mit 0x66 und r17
(0x35 steht da glaube ich drin) und geht weiter, wenn das passt.
Nun stellt sich mir nur die Frage, warum erreicht er da nie ein Ende.
Jedenfalls AVR-Studio, womit ich das simuliere nicht. Er zählt X hoch
und fängt irgendwann von vorne an, so habe ich das gefühl.
Hat hier noch irgendjemand einen Vorschlag. Und wenn - auch warum der
gcc mir so ein komisches Konstrukt erzeugt?
Gruß
Weißt Du schon, an was es gelegen hat?
Ich habe den selben Fehler mit einem Atmega32 auf dem Pollin AVR NET
I/O-Board mit der Firmware von Ulrich Radig.
Auch ich programmiere mit Code::Blocks.
Teils entscheiden nur kleine und unwichtige Details später im Code
darüber, ob der Atmega startet oder schon gleich am Anfang in der ersten
Zeile daran scheitert, eine LED anzuschalten.
Ich habe auch testweise einen Atmega644 gekauft und eingebaut, aber der
ist selbst mit den Codes, die der Atmega32 geschluckt hat, nicht
angesprungen.
Hallo,
bin neu hier im Forum. Bin mit Microprocessorprogrammierung (u.a. 68000)
auch beruflich quasi aufgewachsen.
Ich habe ein ähnliches Problem, wie hier im Thread beschrieben wurde.
Der ATmega32 ist für mich Neuland. Ich habe die Pollin AVR-Net-IO
aufgebaut, die auch funktioniert. Selbst der Ethersex-Webserver läuft
ohne Probleme. Jetzt habe ich einen TCP-IP-Stack in C aus dem Netz mit
selbstgeschriebenen C++ Code gelinkt, was auch erstmal funktionierte.
Dann habe ich einige C++-Routinen zu einer Klasse hinzugefügt. Jetzt
startet der ATmega nicht mehr. Wenn ich die Funktionen leere, also nur
den Rumpf über lasse, startet er wieder. Die hinzugefügten Funktionen
werden beim Start aber gar nicht aufgerufen, werden bei der späteren
Programmablauf benötigt. Es sieht so aus, als wenn irgendein
Speicherbereich überläuft. Mach ich das Programm länger gehts nicht,
mache ich es wieder kürzer, klappt es. Die .map-Datei sagt mir auch
nichts.
Der Programmbereich ist nur zur Hälfte belegt. Der RAM-Bereich fast
leer.
Weiß jemand Rat? Scheinbar bin ich kein Einzelfall.
Gruß,
Michael/SH
Hallo Klaus,
ok, einen eigenen Thread kann ich anlegen. Es ging mir hier eher darum,
ob und wie die Probleme hier gelöst wurden. Vielleicht hilft mit das
weiter. Der letzte Beitrag ist schon ein halbes Jahr alt, da sollte sich
doch was getan haben.
Sorry, dann habe ich dich falsch verstanden.
Dein Problem sieht aber auch etwas anders aus.
Je nachdem, was du in C++ hinzufügst, kann z.B. schnell der
Stack alle sein. Das wäre dann ein reines Problem in deinem
Programm.
Die Methoden werden gar nicht beim Start aufgerufen, benötigen also
keinen Stack. Das ist ja gerade so seltsam. Es scheint sich nur um mehr
Programmcode zu handeln, der dazu führt, dass der Controller nicht mehr
startet. Wenn ich die Methoden leere, also nur den Rumpf über lasse,
funktioniert es ja. Wie schon geschrieben, die Methoden werden beim
Start nicht aufgerufen. Es läuft nur eine Timer, für eine Portausgabe
und der TCP-IP-Stack. Ist alles ok, kann ich das Board anpingen.
Vergrößere ich den Programmcode, läuft der Ping ins leere. Die Methoden
werden erst aufgerufen, wenn IP-Pakete an für einen bestimmten Port
empfangen werden und das passiert nach dem Reset nicht.
M. Franz schrieb:> Die Methoden werden gar nicht beim Start aufgerufen, benötigen also> keinen Stack. Das ist ja gerade so seltsam. Es scheint sich nur um mehr
Ausser den Stack ueberschreiben gibt es aber noch andere Nebeneffekte
wenn man ueber das RAM-Ende hinaus schreibt.
Also beim ATmega8 geht das RAM bis 0x45F. Im Bereich 0 bis 0x1F sind die
Register r0 bis r31. Da fuer die Adresse 0x45F nur 11 Bits benoetigt
werden, werden die andern Bits ignoriert. Somit entspricht die Adresse
0x811 (also 0x800+17) gerade wieder dem Register r17.
Um keinen Quatsch zu erzaehlen habe ich gerade mal ein entsprechendes
kleines Testprogramm gemacht:
1
clr r1
2
ldi XL, low(RAM_START)
3
ldi XH, high(RAM_START)
4
ldi r17, high(0x800+18)
5
mov r18, r17
6
L1: cp r17, r18 ; muesste immer gleich sein
7
brne test2 ; Fehler--> synchrones Blinken
8
st X+, r1
9
cpi XL, low(0x800+18)
10
cpc XH, r17
11
brne L1 ; gesamtes RAM loeschen
12
rjmp test1 ; allos ok --> rotierendes Blinken
Wie erwartet laeuft es mit 0x800+17 noch durch, und bei 0x800+18 wird
r17 veraendert. Haette ich den Test auf unveraendertes r17 nicht drin
wuerde die Schlaufe ewig laufen. Genau das passiert wohl auch beim
Beispielprogramm von Schmidti.
Auch wenn die Variablen welche zu viel Speicher belegen erst spaeter
kommen: der Compiler wird diese Variablen schon vor dem Hauptprogramm
initialisieren. Auch Construkturen in C++ Klassen koennen schon bevor
main() gestartet wird ausgefuehrt werden.
Rolf
Der Hinweis mit dem eingeschränktem RAM-Bereich war der richtige Tipp.
Nachdem ich ein paar Texte in den Programmspeicher verlegt habe,
funktioniert es erstmal. Die Texte benötigen aber nur höchstens 100
Bytes. Den eigentlichen 'Speicherfresser' habe ich wohl noch nicht
gefunden.
Allerdings habe ich noch einen anderen Fehler, den ich noch finden muss.
Trotzdem erstmal vielen Dank für die Hilfe.