Forum: Compiler & IDEs String auf MMC Karte ablegen


von Loki Daelis (Gast)


Lesenswert?

Hochgeschätztes AVR Folk,

ich muss euch nochmal mit einem kleinen Problem belästigen.
Ich bin zur Zeit dabei einen Datenlogger für ein Modellflugzeug zu
bauen. Dieser beinhaltet neben einem Atmega8L@MHz diverse Sensoren und
eine MMC Karte um genügend Werte abspeichern zu können.

Soweit so gut, ich kann die Sensoren auslesen (Floats) und auf die MMC
Lesen und schreiben.

Ich möchte jetzt gerne die 7 Messwerte zu einem String verketten:

*Timestamp#Messwert1#Messwert2#Messwert3 usw.

Dazu brauche ich ca. 64 Byte. Da die MMC Karte 512 Byte Blöcke liest
und schreibt habe ich diese auch mit:

unsigned char mmcbuffer[512]; angelegt.
Wenn ich nun mit strcat(mmcbuffer,Messwert); den String zusammensetzte
macht der Controller die Merkwürdigsten Sachen, vom Reset bis zum
überschreiben von anderen Variablen.

Wenn ich die 512 Byte initialisiere,
unsigned char mmcbuffer[512]={0}; macht er ständig einen Reset.

Habe ich mit meinem einen K zuwenig Speicher?
Muss ich dem Buffer vorher speicher reservieren und nachher wieder
freigeben? Wenn ja, wie mache ich das am schönsten.
Durch das malloc blicke ich nicht so ganz durch.

Bitte um Hilfe!
(*Und bitte nicht meckern,
  sollte dieses eine blöde Frage sein
  -> Ich lerne noch.)

von Loki Daelis (Gast)


Lesenswert?

Sorry,

atmega8@4MHz.

von Jens Renner (Gast)


Lesenswert?

Ich gehe mal davon aus, dass Du mit 1k SRAM tatsächlich zu wenig
Speicher hast. Wahrscheinlich läuft der Stack in die Variablen bzw.
umgekehrt.
Das würde beide Phänomene erklären. Im ersten Fall passieren
unvorhergesehene Dinge (geänderte Variablen). Im zweiten Fall sind
große Teile des Speichers Null, und ein Rücksprung aus einer
Unterroutine (Adresse wird vom Stack geholt) erfolgt zur Adresse Null
-> Reset.

Ich denke, durch das riesige Array, malloc() und andere
speicherintensive Funktionen geht Dir der SRAM aus.
Ich würde das Array nur so groß machen, wie es nötig ist (Timestamp
plus sieben Messwerte) und dann beim Beschreiben der MMC automatisch
den Rest mit Nullen füllen.

Jens

von OldBug (Gast)


Lesenswert?

Das größte Problem ist wohl, daß Deine Messwert"strings" nicht
Terminiert sind, und strcat dann fleissig bis zur nächsten
Speicherstelle mit 0x00 oder bis an das RAM-Ende alles in mmcbuffer
kopiert.

Dein String müsste so aussehen:

*Timestamp#Messwert1#Messwert2#...#Messwert7\0

Das kannst Du einfach mache, indem Du beim Erstellen der Strings \0
anhängst, oder den string in "" setzt:

buf[BUFLEN] = 0x00;
buf[BUFLEN] = '\0';
sprintf(buf, "*%s#%s#%s#%s#%s#%s#%s#%s");

von Matthias (Gast)


Lesenswert?

Hi

da das auch beim Initialisieren passiert würde ich eher darauf tippen
das das SRAM nicht ausreicht. Obwohl 1k eigentlich für einen 512 Byte
Puffer + ein bischen Kleinkram + Stack reichen sollte. Was legst du
denn noch an Variablen an?

Matthias

von OldBug (Gast)


Lesenswert?

Beim Initialisieren?
Die Null wird ja nicht "nach hinten" geschoben, wenn er
reinschreibt...

von lokidaelis (Gast)


Lesenswert?

Hallo Jungs,

Danke für die vielen guten Antworten!
Werde nachher mal probieren eure Ratschläge inezubauen.

@Matthias: Ausser dem 512er Brocken sinds halt die 7 float.
1 float = 4 Byte * 7 = 28Byte
Sollte also noch passen...

@OldBug: Das mit der String terminierung ist ein guter Tipp,
daran könnte es evtl. liegen...

@Jens: Sollte mann so ein Malloc auf AVRs Sinnvollerweise bei solchen
Vorhaben einsetzten?
Wenn ja, wie? Ich blick durch die Doku nicht ganz durch.
Da steht in der Funktion:
malloc(wievielspeicherreservieren);
An welcher Stelle sage ich, wofür er reservieren soll?



Werd nachher mal Berichten was es gegeben hat!

Danke!

von Matthias (Gast)


Lesenswert?

Hi

Malloc würde ich nicht tun. Unnötiger Overhead und bringt nichts.

@OldBug
Doch. Wenn du eine Array so:
unsigned char mmcbuffer[512]={0};
anlegst werden alle Elemente mit 0 initialisiert. Wenn das Array
global ist wird es so oder so mit 0 initialisiert.

@lokidaelis
Wie legst du dein Array denn an? Auf dem Stack (also lokal in einer
Funktion) oder global?

Matthias

von lokidaelis (Gast)


Lesenswert?

@Matthias: Ich lege den Buffer global an.

Die Stringterminatoren waren die Lösung!
Mann kann also doch mit einem Mega8 vernünftig mit MMC Karten
arbeiten.

Danke an alle!

von OldBug (Gast)


Lesenswert?

Matthias: Es ging ja nicht um den MMCBuffer ;) sondern um die Strings,
die in den MMCBuffer geschrieben werden.

von nobody0 (Gast)


Lesenswert?

Das mit den Strings ist ein häufiger Anfänger-Fehler, denn man
vermeidet, indem man
fgets      statt     fget
calloc     statt     malloc
strncat    statt     strcat
strncpy    statt     strcpy
snprintf   statt     sprintf
strncmp    statt     strcmp
vsnprintf  statt     vprintf
verwendet.
Deshalb verwende ich nur die linken Funktionen soweit es geht (sowas
wie calloc gibt's anscheinend nicht im kernel-space).
Wenn man Strings fester Länge verwendet, beispielsweise Blöcke von
Daten, dann braucht man die nicht zu terminieren.

von OldBug (Gast)


Lesenswert?

Wie auch immer: man muss_ wissen _was man macht!

Entweder weis ich, daß ich Strings mit 0 Terminieren muss, oder ich
weis, daß der zu kopierende String genau 256bytes hat. Ansonsten geht
auch strncpy in die Hose...

Natürlich helfen solche Funktionen, etwas mehr darüber nachzudenken,
was man da überhaupt macht und wie die verwendeten Funktionen arbeiten!

von nobody0 (Gast)


Lesenswert?

Das strncpy geht nie in die Hose, wenn man immer einen vorhandenen
Datenblock ausliest und dessen Länge in strncpy angibt. Das ist ja
gerade der Vorteil.

von OldBug (Gast)


Lesenswert?

Sicher sicher! Das sagte ich ja auch, aber dann muss man vorher die
größe Wissen...
Man sieht nicht selten, daß dann mal eben ein "etwas größerer Buffer"
angelegt wird, damit auch ja alles reinpasst ;-)
Also ein Allheilmittel ist das auch nicht. Ein guter Versuch, solche
Fehler auszumerzen, aber ohne darüber nachzudenken kann man das alles
auch nicht einsetzen.

Achja: calloc wirds wohl im Kernelspace nicht geben, weil das
Initialisieren mit Null Zeit kosten dürfte...

Naja, ich wollte diesen Hinweis Deinerseits keineswegs schlechtreden
:-)
Das sollte nur eine kleine Erweiterung darstellen...

Gruß,
Patrick...

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.