Forum: Mikrocontroller und Digitale Elektronik atmega8 stürzt bei Funktionsaufruf ab - jedoch schon bevor dieser erreicht ist?


von ... dartrax .. (Firma: www.dartrax.de) (dartrax)


Angehängte Dateien:

Lesenswert?

Hi,
bin ziemlich neu in der Mikrocontrollerprogrammierung und kenne noch 
nicht die "Gemeinheiten" des atmega8 ;-)

Ich versuche, Ulrich Radigs SD-Kartenlesecode (link s. u.) in meinem 
Projekt umzusetzen.
http://www.ulrichradig.de/home/index.php/avr/mmc-sd

Dazu habe ich alles bis auf die usart-Dateien eingebaut und die SD-Card 
natürlich auch physikalisch mit den SPI-Pins des atmega8 verbunden, so 
wie in der vereinfachten Schaltung angegeben:
http://www.ulrichradig.de/site/atmel/avr_mmcsd/gfx/MMCSDSCH.JPG
Es wird die Konfiguration für Hardware-SPI verwendet.

Wenn ich das Programm mit der main.c so wie sie im Anhang ist in dem 
atmega ausführe, sehe ich auf dem Display:
Hello! -> SUCHE SD-CARD -> SD GEFUNDEN -> Hello! -> ... wieder von vorne 
und immer so weiter. Ich nehme an, wegen irgend etwas stürzt der 
Controller ab und startet von vorn. Jetzt geht die Fehlersuche los.

Wenn ich die Zeile fat_cluster_data_store(); auskommentiere, geht's 
weiter, nämlich bis er mit der Anzeige "HAUPTSCHLEIFE" aufhört. Soweit, 
so gut und nachvollziehbar, wenn man davon ausgeht, dass da irgendwo der 
Fehler ist.

Was mich aber irritiert ist, dass er auch dann bis "HAUTPSCHLEIFE" 
kommt, wenn man fat_cluster_data_store(); drinn lässt, aber die beiden 
Zeilen
mmc_read_csd (Buffer);
und
Clustervar = fat_read_dir_ent(0,a,&Size,&Dir_Attrib,Buffer);
auskommentiert!!!
Das bedeutet doch im Umkehrschluss, wenn man diese nicht auskommentiert, 
dann "weiß" der Microcontroller bereits bevor er bei der Ausgabe von 
"TEST" ist (denn da stürzt er ja dann schon ab), dass die beiden 
Funktionen mmc_read_csd und fat_read_dir_ent demnächst kommen werden und 
beschließt, lieber rechtzeitig abzustürzen?!
Ich kann mir das leider nicht erklären, eigentlich stürzen Programme 
doch erst ab, wenn sie den Fehler erreicht haben??

Ich habe dann gedacht, vielleicht ist der Fehler in einem "parallelen" 
Programmteil und habe die sei(); auskommentiert, um die Interrupts zu 
deaktivieren, hat aber nichts gebracht.

Nun denke ich, gibt es irgend eine Beschränkung derart, dass sich der 
Code zu weit verzweigen und verschachteln würde, wenn nicht ein oder 
zwei Funktionen auskommentiert sind? Dann könnte ich mir ja noch 
vorstellen, dass der atmega zu früh abstürzt...

Oder ich steh' einfach auf'm Schlauch.

Vielen dank,
dartrax

PS: Ach ja, einiges in meinem  Code sieht bestimmt "schrecklich" aus, 
ich lerne noch ;-)

von Marvin M. (Gast)


Lesenswert?

Schonmal darüber nachgedacht, dass der Speicher des Mega-8 zu klein 
ist... ?
Welchen Controller hat denn Ulrich Radig verwendet - und warum?

von ... dartrax .. (Firma: www.dartrax.de) (dartrax)


Lesenswert?

Klar habe ich darüber nachgedacht, deshalb habe ich das ja im untersten 
Absatz wissen wollen, ob es da so eine Beschränkung gibt. Leider bist du 
mir die Antwort schuldig geblieben.

Von der Größe her passt das Programm locker, mit dem FAT und SD-Code ist 
er von etwa 43% auf 74% angewachsen.
Der MP3-Player hier in der ersten Version verwendet erfolgreich einen 
Atmega8L, ich hatte diesen Code für den SD-Zugriff zuvor ausprobiert und 
die Größe belief sich auf 99%. Deswegen glaube ich, dass es schon 
machbar sein sollte, aber lasse mich natürlich auch eines besseren 
belehren.
http://members.liwest.at/dobretsb/stephan/schaltung.html

dartrax

von Spess53 (Gast)


Lesenswert?

Hi

Und wie sieht es mit dem RAM aus? Ich tippe eher auf Stackfehler.

MfG Spess

von ... dartrax .. (Firma: www.dartrax.de) (dartrax)


Lesenswert?

Hallo!
Danke für deine Antwort.
Der Compiler zeigt an:

Program:    6100 bytes (74.5% Full)
(.text + .data + .bootloader)

Data:        253 bytes (24.7% Full)
(.data + .bss + .noinit)


Was ist ein Stackfehler? Habe leider nur einen Suchbegriff gefunden. Wie 
finde ich das raus?

dartrax

von Andreas K. (a-k)


Lesenswert?

Der Blick auf statische Daten hilft nicht viel weiter, wenn das Programm 
den grössten Teil seiner Daten auf dem Stack anlegt. Das betrifft also 
alle Daten, die in einer Funktion definiert und nicht ausdrücklich als 
"static" markiert sind.

Hier beispielsweise liegt Buffer[] mit 512 Bytes auf dem Stack und 
taucht daher in der Angabe des belegten RAMs nicht auf. Frisst aber 
bereits die Hälfte davon weg.

von Spess53 (Gast)


Lesenswert?

Hi

Der Stack ist in Speicherbereich, der vom oberen Ramende nach unten 
'wächst'.
Bei Unterprogrogrammaufrufen werden z.B. die Rückkkehradressen abgelegt. 
Compiler benutzen den auch zur Veriablenübergabe. Wenn der Stack in den 
RAM-Bereich kommt, der auch von deinem Programm genutzt wird, werden 
essentielle Daten überschrieben und es kommt unweigerlich zum Absturz.

MfG Spess

von Marvin M. (Gast)


Lesenswert?

Genau darauf wollte ich hinaus. Ich habe bislang noch keinen Code für 
FAT gesehen, der in einen Mega-8 gepasst hat - meist ist ein Mega-16 
Mindestanforderung. Und seltsame, nicht nachvollziehbare Abstürze 
riechen geradezu danach, dass es ein Stack-Problem ist.
Ergo: Größeren Controller nehmen oder den Code so umschreiben, dass es 
passt.
Auf die Angaben des Compilers kannst Du Dich überhaupt nicht verlassen, 
weil bei der Belegung des RAM nicht die dynamischen Komponenten (z.B. 
lokal definierte Variablen) berücksichtigt werden.
Ich würde die erste Variante nehmen ;-)

von Benedikt K. (benedikt)


Lesenswert?

Marvin M. wrote:
> Ich habe bislang noch keinen Code für
> FAT gesehen, der in einen Mega-8 gepasst hat

Dann hast du aber bisher zu wenige gesehen.
Ich kenne 3 Dateisystemroutinen, und alle 3 laufen auf einem mega8.
- eines von mir
- das tiny Filesystem von ELM Chan
- das von Ulrich Radig

Das von Chan sogar in Schreib/Lese Konfiguration.

von ... dartrax .. (Firma: www.dartrax.de) (dartrax)


Lesenswert?

Ich glaube, dass ihr Recht habt und es am geringen Speicher liegt. Wenn 
ich nämlich spaßeshalber den
unsigned char Buffer[512];
auf [12] verringere, stürzt es nicht ab.

Da ich den Buffer jedoch brauche, muss ich sehen, warum vor dieser 
Deklaration irgendwo innerhalb des fat_cluster_data_store()-Aufrufs 
nochmal so viel Speicher verbraucht und scheinbar nicht wieder 
freigegeben wird (???).

Es wird bereits innerhalb von fat_cluster_data_store() ein Buffer 
deklariert:
unsigned char Buffer[BlockSize]; (BlockSize ist 512)
Dann folgt der Aufruf
... = fat_addr (Buffer);
Diese Funktion enthält zwei Aufrufe von mmc_read_sector(...). Sobald ich 
beide auskommentiere, funktioniert's. Lasse ich sie drin und kommentiere 
den gesamten Inhalt der Funktion mmc_read_sector aus, funktioniert's 
nicht mehr!
Der Unterschied liegt doch lediglich in einem weiteren Funktionsaufruf. 
Keine weiteren Variablendeklarationen, nichts. Heißt dass, dass hier der 
Rückkehradressen-Stack überläuft?

Der RAM müsste zu diesem Zeitpunkt 86 bytes (Compilermeldung, ich habe 
andere Funktionen entfernt, die ich im Moment nicht brauche) + 512 Bytes 
(Deklaration des Buffers) + ein paar weitere Deklarationen betragen. 
Eigentlich sollte Platz sein...?

dartrax

von Benedikt K. (benedikt)


Lesenswert?

... dartrax ... wrote:
> Da ich den Buffer jedoch brauche,

Dann mach ihn mal global. Dann wird dieser Verbrauch schonmal beim 
compilieren mitgezählt.

> Es wird bereits innerhalb von fat_cluster_data_store() ein Buffer
> deklariert:
> unsigned char Buffer[BlockSize]; (BlockSize ist 512)

Könntest du die Datei mal hier reinstellen ?

von Spess53 (Gast)


Lesenswert?

Hi

Mir wird immer klarer, warum ich in Assembler programmiere. Danke.

MfG Spess

von ... dartrax .. (Firma: www.dartrax.de) (dartrax)


Angehängte Dateien:

Lesenswert?

Gute Idee^^
Die fat und mmc-Dateien von Ulrich Radig sind in den Anhängen (der 
folgenden Posts).

Ich habe "ertestet", dass der Buffer bis 480 bytes das Programm in Ruhe 
lässt, bei 481 wird's kritisch (gibt "HAEPTSCHLEIFE" statt 
"HAUPTSCHLEIFE" am Ende aus), ab 482 stürzt es in der Routine ab.
Ich habe ihm eben mal ein "static" davor gesetzt, Compiler sagt jetzt:
Data:        599 bytes (58.5% Full)


@Spess53
Man gewöhnt sich an alles.
Auch an deine Spitzbübigkeiten ;-)

dartrax

von ... dartrax .. (Firma: www.dartrax.de) (dartrax)


Lesenswert?

fat.h - Sorry, hat nicht geklappt. Kommt weiter unten.

von ... dartrax .. (Firma: www.dartrax.de) (dartrax)


Angehängte Dateien:

Lesenswert?

mmc.c

von ... dartrax .. (Firma: www.dartrax.de) (dartrax)


Angehängte Dateien:

Lesenswert?

mmc.h

von Benedikt K. (benedikt)


Lesenswert?

Da Cluster Data Store ja nur ganz am Anfang aufgerufen wird, kannst du 
eigentlich auch den globalen Buffer dafür verwenden. Entferne als die 
Zeile aus der Funktion, und mache Buffer[512] global. Dann sollte das 
ganze mit 512 + ein paar Bytes auskommen.

von ... dartrax .. (Firma: www.dartrax.de) (dartrax)


Lesenswert?

JUCHHEEEEYYY!!!!!

Die SD hat gerade ihre Ordner- und Dateinamen im Root auf dem Display 
preisgegeben!

Die Fehlerursache und dein Tipp, Benedikt, waren goldrichtig!

DAANKEE!!

dartrax

von VooChee (Gast)


Lesenswert?

Hi  ... dartrax ...

könntest du mal deine Version der mmc.c und main.c posten?
Ich habe nämlich das gleiche Problem mit der Allocation des Buffers auf 
einem ATmega88

VooChee

von ... dartrax .. (Firma: www.dartrax.de) (dartrax)


Angehängte Dateien:

Lesenswert?

Hi!

Ich hab dir den Code in den Anhang gepackt. Einige Funktionen, die ich 
inzwischen hinzugefügt hatte für andere Funktionen habe ich in deiner 
Kopie entfernt, aber ich kann's im Moment leider nicht testen, ob's noch 
funktioniert, da ich gerade "auf dem Sprung" bin. Wenn du Probleme hast, 
kann ich vorr. Dienstag/Mittwoch nochmal reinschauen.

Die Deklaration des Buffers ist in fat.h, ich habe insgesamt aber nur 
wenige Zeilen ändern müssen.

Im Anhang ist auch ein Screenshot, wie du die SD-Karte mit der 
Kommandozeile (XP) formatieren solltest, wobei du den Wert für a so 
anpassen musst (halbieren/verdoppeln), dass hinterher "16 Bits in jedem 
FAT-Datensatz" übrig bleiben.

Die SD-Karte ist wie von Ulrich Radig vorgeschlagen angeschlossen:
http://www.ulrichradig.de/site/atmel/avr_mmcsd/gfx/MMCSDSCH.JPG
Verwendet werden die SPI-Pins des atmega8, das ist voraussetzung wenn 
man den Hardware-SPI (wie ich) verwenden will (was mir vorher nicht ganz 
klar war). Die Pinbelegung siehst du in mmc.h.

Viel Erfolg!
dartrax

von VooChee (Gast)


Lesenswert?

Hi dartrax

habe es mit deinem Codebeispiel nun auch auf einem ATmega88 zum laufen 
gebracht. Meine globale Buffer-Variable war irgendwie nicht so global 
wie deine :)

Einige Probleme die ich hatte rührten daher, das ich den ISP noch 
draufstecken hatte, was sich scheinbar mit dem SPI nicht verträgt.

THX
VooChee

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.