Hallo.
Ich habe eine Atmega32 mit einem S65 LCD und einer SD karte am laufen.
Die SD karte läuft mit dem Code von Ulrich R.
Leider habe ich seit ein paar Wochen sehr komische Probleme mit der
Schaltung.
Mein Code ist mit der zeit am wachsen. logisch.
aber jetzt das komische verhalten vom avr.
Es ist so, das wenn ich eine neue Funktion "hinzufügen" in der lib fürs
LCD, funktionier mein gesamtes Programm nicht mehr sauber. das LCD zeigt
nur noch schrott an. Und das, obwohl die Funktion gar nicht aufgerufen
wird?
Wenn ich in der Main Funktion hinter der LCD Ausgabe etwas auf der uart
ausgeben möchte, habe ich ähnliche Fehler verhalten. nehme ich die uart
Geschichte wieder raus, läuft es.
Achso, das Bild wird auf der SD karte gefunden, und auch geladen.
Kann es sein, das mein RAM im AVR defekt ist vom (vielen) programmieren?
Oder kann es am AVR Studio liegen? Habe die Version 4.14.
Achso, sobald ich den compiler aus eine andere optimierung einstelle,
bekomme ich auch ein ähnliches verhalten, das das LCD nur noch mist
anzeigt, bzw. er den Bild bereich ändert.
vieleicht hat jemand eine lösung für mich.
ich weiß nicht wirklich, wo ich anfangen soll zu suchen.
Klingt nach einer möglichen ursache.
Bedeutet das ein Programmier fehler?
Oder defekter RAM?
Wie kann ich es überprüfen, und falls es der fall sein sollte, beheben?
laut ockhams razor wirds an deinem code liegen ;).. hast du keine
simulationsmöglichkeit? oder hardware debugger? in der software
irgendwelche debug-ausgabe möglichkeit? ich habe für debug ziemlich viel
code investiert, damit ich per uart alles mögliche an internen zuständen
ausgeben kann, sowie umfangreiche exception try-catch konstrukte
(allerdings in asm).. ohne alles das wäre ich nie weitergekommen, und
auch mit diesen möglichkeiten hilft manchmal nur das simulieren. wenn
fehler sich eingrenzen lassen, in dem du bestimmte programmteile
rausnimmst, weißt du ja schon wo du anfangen musst. weiter eingrenzen
lässt sich es in dem du zu debugzwecken den code weiter veränderst, und
die auswirkung auf das fehlerbild analysierst. oft zeigt sich z.b. am
zeitpunkt des auftretens was der auslöser sein könnte. wenn dein
programm sofort beim einschalten abschmiert kommt man mit dem simulator
schnell weiter, da man nicht viele taktzyklen warten muss.
wie immer gilt, ohne weitere infos, quellcode, kann man kaum mehr als
das orakel befragen...
>Bedeutet das ein Programmier fehler?
In gewisser Weise schon ;)
>Oder defekter RAM?
Nein.
>Wie kann ich es überprüfen, und falls es der fall sein sollte, beheben?
Man kann durch exzessive Nutzung von z.B. printf()
ganz schön viel RAM verbrauchen. Da liegen die auszugebenden
Strings im RAM. Wenn man printf_P() nimmt liegen sie im Flash.
Ist aber nur ein Beispiel. Wo du RAM vernichtest kann uns
nur dein Code verraten.
gast wrote:
> Klingt nach einer möglichen ursache.> Bedeutet das ein Programmier fehler?> Oder defekter RAM?
Nein, das bedeutet, dass dein Programm mehr RAM-Speicher benötigt als
der Baustein zur Verfügung stellt, der ATmega32 hat "nur" 2-Kbyte SRAM
dein Programm bräuchte aber möglicherweise 3KB, 4KB oder noch mehr SRAM.
> Wie kann ich es überprüfen,
Du könntest dir evt. an bestimmten Stellen den Inhalt des Stackpointers
ausgeben lassen, also wenn der Stack beim AVR von oben nach unten wächst
und der Stackpointer plötzlich "ganz unten" ankommt, also z.B. bei 0000
oder 0002, (läuft das so beim ATmega?), dann spricht vieles dafür, dass
du zu wenig SRAM hast, dann kann alles durcheinander kommen: Variablen
werden überschrieben, Unterprogramm und Interruptrücksprungadressen
gehen verloren, usw. ...
> und falls es der fall sein sollte, beheben?
Einen Prozessor mit mehr SRAM besorgen z.B. den ATmega644 (mit 4KB
SRAM), oder externes RAM verwenden, (eher unpraktisch). Oder mal dein
Programm durchschauen: Rekursive oder sehr verschachtelte
Unterprogrammaufrufe brauchen viel RAM, und, (da hab ich leider noch
nicht allzu viel Ahnung von Win-AVR-C), möglicherweise kannst du was
retten wenn du darauf schaust, dass alle Funktionsparameter "By
Reference" d.h. als Pointer und nicht als Speicherkopie d.h. "By Value"
übergibst. Umfangreiche Stringmanipulationen sind bei 2KB Ram wohl auch
nicht drin.
Im Prinzip musst du dir bei jeder Funktion, bei jeder Schleife und bei
jeder zur Laufzeit angelegten Variable überlegen wieviel RAM dafür wohl
verbraucht wird.
Nachtrag:
Gerade mal kurz in deinen Code reingeschaut, (wie gesagt, hab da nicht
viel Ahnung von), aber wenn ich nur 2KB SRAM hätte, würde ich nicht so
verschwenderisch mit den "char filefound[20]" etc. um mich werfen...
Alle Stringkonstanten müssen ins Flash, (oder optimiert das der
Compiler?).
Und der "unsigned char Buffa3[512];" da ist ja schon mal von vornerein
ein Viertel des RAMs auf einen Schlag weg.
> Alle Stringkonstanten müssen ins Flash, (oder optimiert das der> Compiler?).
Der Compiler optimiert das nicht.
Die Stringkonstanten sind zwar im Flash, werden sie aber nicht auf eine
spezielle Weise deklariert und über eine Spezialfunktion gelesen,
sondern einfach nach der Methode
"usart_write("------------------------------------------\n\n");"
eingetragen, dann werden diese Konstanten beim Programmstart ins RAM
umgeladen. Da bleibt dann für den Stack nichts mehr übrig.
Besser man macht es so:
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Array_aus_Zeichenketten_im_Flash-Speicher
Gruß
Jadeclaw.
Schade, ich dachte der compiler meldet sich mal, wenn er merkt falls es
eng wird.
Der hätte ja nun wirklich den überblick.
"Buffa3[512];" wird in einer Funktion deklariert.
Wenn ich diese Funktion jetzt dreimal aufrufe, belegt sie doch nur
einmal den speicher, oder habe ich da grundsätzlich irgendwas noch nicht
verstanden?
nein, der speicher wird jedesmal reserviert. er wird zwar (im
normalfall) wieder freigegeben, aber wenn z.b. nur mehr 300 kB ram übrig
sind, es werden aber 512 benötigt gibts schon probleme.
wie die speicherverwaltung auf dem avr in c funktioniert weiß ich leider
nicht genau, programmiere in asm...
Zweiter Gast wrote:
> Hmm, hilft da "static unsigned char Buffa3[512];" ?
Dann werden die 512 Bytes eben dauerhaft belegt, (könnte aber
vielleicht, in anderen Situationen, unter gewissen Umständen, wenn man
das gleich beim Programmstart mit allen dauerhaft benötigten Buffern
macht, dabei helfen, die Speicherfragmentierung zu verringern).
Aber das Grundproblem bleibt dasselbe: Nur 2024 Bytes RAM die sich
Variablen und Stack teilen müssen.
Erstaunlich.
Durch ein wenig optimierung und ausklammern von "usart_write"
funktioniert es jetzt.
An einen Stacküberlauf habe ich überhaupt nicht gedacht.
Ein "Danke" an alle beteiligten.