www.mikrocontroller.net

Forum: Compiler & IDEs String auf MMC Karte ablegen


Autor: Loki Daelis (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.)

Autor: Loki Daelis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry,

atmega8@4MHz.

Autor: Jens Renner (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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");

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: OldBug (Gast)
Datum:

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

Autor: lokidaelis (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: lokidaelis (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: OldBug (Gast)
Datum:

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

Autor: nobody0 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: nobody0 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.