Hallo
ich möchte diesen Thread nicht verwässen und habe deshalb einen neuen
Thread gestartet.
Wie sieht es mit der Lebensdauer der Karte aus, wenn man pro Sekeunde
kleine Einheiten schreibt?
Ist das unsinnig?
Wie sollte man da vorgehen?
MfG
Achim
siehe ==>Beitrag "SD Card GPS Logger optimieren?"
Hallo.
@Onit
Da ein '\n' halt auch nur ein Char/Byte ist, wird da schon nix doppelt
gezählt..
@Sucher
Bei meiner Lib werden halt immer 512 Bytes zwischengespeichert, da auch
immer 512 Bytes direkt auf die Karte müssen. Daher ist die Langlebigkeit
genau so, als wenn ein Pc auf die Karte schreibt...Nur das der
vielleicht noch bisschen mehr Puffert als es mit einem MC möglich ist..
Grüße Daniel
Hallo
@Daniel das heißt, wenn ich kleinere Einheiten als 512 Byte schreibe
wird das in deinem Interface gepuffert? Muss man da beim Schreiben dann
die Bytegrenzen (512 Byte Blockung) als Anwender beachten?
Es wird also solange gepuffert bis 512 Byte erreicht sind. Wenn ich nun
einen String schreibe der über die 512 Byte geht wird dann ein 512 Byte
String auf die SD Karte geschrieben und der Rest gepuffert? Wenn nur
gepuffert wird ist der Schreibvorgang schneller, als wenn eine
Blockgrenze überschritten wird und auf die SD geschrieben wird. Wie
lange dauert dann dieser Aufruf (klar Proz abhängig)?
Wird bei jedem Blockschreiben die FAT auf der SD Karte aktualisiert?
Falls ja wäre das ja der kritische Punkt mit dem "kaputt" gehen der SD
Karte, oder wird nur beim Schließen des Files aktualisiert?
Fragen über Fragen...
Vielen Dank
Achim
Hallo Sucher,
ja richtig. In der Lib gibt es einen 512Byte Puffer. Ist dieser voll,
wird die Karte mit diesen Bytes beschrieben.
Erst bei ffclose() erfährt der Dateieintrag und die Fat eine
Aktualisierung. Es werden immer freie Cluster in einer Reihe gesucht,
ist diese Anzahl voll, so werden diese auch schon in der Fat verkettet.
Wird erst zum Problem, wenn die Fat total fragmentiert ist...
Eine Datei bei FAT-Dateisystemen ist Quasi in 3 Teile aufgeteilt:
1. Datei Eintrag mit Name,länge usw in einem Ordner.
2. FAT Einträge
3. Die Daten selber
Siehe auch: http://www.mikrocontroller.net/articles/AVR_FAT32
Wer mag kann mit "int i=file.cntOfBytes;" abfragen wie viele Bytes in
dem Puffer schon geschrieben sind. Bei 512 wird auf die Karte
geschrieben...
Wie lange jetzt genau das schreiben eines 512Byte Blocks dauert müsste
man mal testen :)
Ebenso wie lange es dauert neue freie Cluster aus der Fat zu suchen oder
solche Cluster zu verketten...
Grüße Daniel
Hallo
@Daniel noch ne Frage(n): Kann man beim Öffnen ne Dateigrösse angeben,
dass die entsprechenden Cluster gleich vekettet werden, ohne dass man da
explizit reinschreibt?
Oder geht das mit ffseek übers Dateiende hinaus...wird dann reserviert,
oder darf bei ffseek der Offset nicht übers Dateiende rausgehen?
Gibts dafür ne andere Möglichkeit?
Vielen Dank
Achim
Moin,
also ffseek() darf auf keinen Fall über das Dateiende hinaus. Gilt nur
für innerhalb einer Datei, bis zum letzten Byte.
Also vorher die Datei Größe bestimmen? Wieso?
Wäre schon machbar, mir erschließt sich aber nicht der Grund wieso man
das machen sollte.
Wenn es um Geschwindigkteit geht, einfach dafür sorgen, dass die Fat
nicht fragmentiert ist. dann könnten bis zu 65000 Cluster am Strück mit
Daten voll gemacht werden, bevor diese verkettet werden müssen (müsste
man nur 2 Zahlen in der Lib ändern).
Mal mit Zahlen:
4 Sektoren Pro Cluster.
512 Bytes Pro Sektor.
65000 Cluster.
Macht 126,95 Mega Bytes am Stück, ohne etwas mit der Fat oder dem
Dateieintrag machen zu müssen :)
Bei 65000 Clustern, die in der Fat verkettet werden müssen, müssen 508
Fat Sektoren geschrieben werden, macht 206096 Bytes. Also etwa 254
KBytes. Die bekommt man so in etwa 2 Sekunden beschrieben...
Grüße Daniel
Hallo
@Daniel ich bin eben dabei die einzelnen Implementierungen abzuklopfen.
In der Implementierung von Roland Riegel wird sowas diskutiert, dass man
am Anfang gleich einen großen File allokiert weil sonst das Anfügen
lange dauert.
zB.:Beitrag "Re: MMC/SD-Karte mit FAT16 an AVR"
Ich muß halt mal damit spielen und Erfahrungen sammeln...
Vielen Dank
Achim
Hi Achim,
den Code von Roland versteh ich teilweise nicht genau.
Aber generell dauert es halt ein bisschen die Fat zu updaten und neue
freie Cluster zu suchen.
Zuerst hatte ich da auch eine etwas sperrige Methode. Jetzt geht das
total schnell, wenn halt die Fat nicht groß fragmentiert ist.
Wenn du da irgendwo Vorteile/Nachteile siehst, könnte man das ja mal
zusammen tragen und als Vergleich ins Wiki stellen...
Grüße Daniel
PS: hab mich da oben bei einer Ziffer vertan, muss natürlich 260096
Bytes heißen^^
Hallo,
sehr seltsam. Wie kommst du denn auf -492 ?
Weil eigentlich dachte ich das ein "unsigned long int length" (siehe
fat.h) niemals negativ werden kann.
Lässt du dir das vielleicht falsch anzeigen?
Nimm mal die neue Version, vielleicht wirds dann besser.
Hab jetzt auch die bekannten Bugs beseitigt.
Es gibt 2 neue Schalter in der fat.h.
1. OVER_WRITE
Gibt an ob die Datei überschreiben Funktionalität mit Kompiliert wird.
Da wenn überschrieben wird auch immer der zu überschreibende Sektor
geladen werden muss, ist meine Empfehlung "OVER_WRITE 0" zu setzen und
auf überschreiben zu verzichten.
2.MAX_CLUSTER_IN_ROW
Gibt an wie viele verkette bzw. leer Cluster für eine Datei gesucht
werden, maximaler Wert, 65 534.
Grüße Daniel
Inzwischen habe ich es herausgefunden: warum der unsigned long int nun
negativ war weiß ich nicht, aber deine Lib hat mir die Datei 4GB groß
gemacht, obwohl die Karte nur einen GB hat... nun gehts aber.
Hallo,
ja das mit der Dateigröße ist mir dann doch noch klarer geworden. Unter
Umständen waren auf file.length noch alte Daten vom durchsuchen von
alten Ordnern... hatte da aufgrund von Codegröße alles mögliche gekürzt
^^
Da überschreiben von Daten so kompliziert ist und deshalb relativ
langsam, gibt es 2 Funktionen zum schreiben, die über den schon
erwähnten Schalter OVER_WRITE in fat.h wahlweise mit ein Kompiliert
werden können.
Der Code ist diesmal wirklich stabil, da ich ausgiebig Zeit zum testen
hatte.
Anregungen und Tipps immer willkommen.
Als Anhang die neue Version mmc-0.5.3
Es ist dringend zu empfehlen, entweder die Version mmc-0.4.8 oder die
neue zu benutzen !
Grüße Daniel
Hallo
@Daniel mal ne blöde Frage "Wann wird eine FAT fragmentiert"?
..doch nur wenn ich eine Datei schließe ne neue öffne und schreibe
schließe und die alte Datei öffne und was dran hänge...
oder eine Datei lösche und ne neue mit verschiedener Größere schreibe?
Macht es da nicht Sinn (meine oben gestellte Frage) dass man beim Öffnen
oder seek die Deitei auf eine bestimmte grösse aufblähen kann ohne
reinzuschreiben?
MfG
Achim
Hallo Achim,
eine Fat fragmentiert, wenn man Daten löscht. weil da wo vorher die
Cluster einer Datei in der Fat verkettet waren, nun Cluster frei sind.
Die von Dir beschriebenen Probleme sind dann nur die Folge draus...
Das Problem ist, ich möchte die Lib so allgemein wie möglich halten.
Natürlich müsste man, wenn etwas sehr Zeitkritisch ist testen und ggf.
die Lib anpassen.
Oder sogar alles auf eine spezielle Gegebenheit umschreiben und zusammen
kürzen. Mir geht da z.B. eine Einzige Funktion durch den Kopf, die eine
ganze komplett vordefinierte Datei schreibt oder ähnliches...
Das mit dem vorher allozieren wäre garkein Problem, nur ich gehe mal
davon aus, nicht vorher zu wissen wie lang eine Datei wird.
Vielleicht baue ich noch ein, dass man beim schreiben immer mindestens
MAX_CLUSTERS_IN_ROW freie bekommt. Und/Oder eine Funktion, die die
letzte Datei in der Fat ermittelt und erst danach mit schreiben anfängt.
Grüße Daniel
Hallo,
ich versuche gerade den Code zu verwenden, leider ohne den gewünschten
Erfolg. Ich habe die letzte Version benutzt und momentan sieht mein Code
so aus:
[c]
int main (void)
{
//wdt_enable(WDTO_1S);
sei();
initUart();
sendEOL();
uartPutS("Serveur de temps");
sendEOL();
if(mmc_init() == 0)
{
uartPutS("SD-Card Inizialisation failed.");
sendEOL();
while(1) {};
}
uartPutS("SD-Card initialized.");
sendEOL();
if (fat_initfat() == 0)
{
uartPutS("FAT initialized.");
sendEOL();
char datei[12]="test.txt";
fat_str(datei);
switch (ffopen(datei ))
{
case 1:
{
uartPutS("Existing file opened.");
sendEOL();
}
case 2:
{
uartPutS("New file created and opened.");
sendEOL();
}
default:
{
uartPutS("Cannot create or open file.");
sendEOL();
}
}
ffwrites((char*)"Hallo Datei :)");
ffwrite(0x0D);
ffwrite(0x0A);
uartPutS("Data written to file.");
sendEOL();
ffclose();
uartPutS("File closed.");
sendEOL();
}
while(1) {};
}
[\c]
Die Initialisierung klappt, nur beim ffopen() bzw genauer in der Routine
unsigned char fat_loadFileDataFromDir(char name[]) hängt der Prozessor
sich auf. Nach meinen bisherigen Nachforschungen sind die ausgelesenen
Sektoren alle '0' und der Prozessor hängt. Auf dem SPI-Bus ist nichts
mehr los. Was mich wundert: Die Karte wird als FAT32 erkannt, auch wenn
sie auf FAT16 formatiert wurde. Ich habe sowohl FAT32 als auch 16
ausprobiert und auch SUPERFLOPPY geändert, ohne Erfolg.
Hat jemand eine Idee, woran es liegt?
Da es sein kann das es etwas dauert bis die Karte "anspringt".
Sieht sonst OK aus.
Vielleicht mal den SPI Takt bisschen runter setzen.
Wie hast du die Karte angeschlossen?
Grüße Daniel
Der SPI-Takt liegt bei etwa 120kHz, die Karte ist direkt an einen
Atmega644p angeschlossen, der mit 3,3V läuft. Ein Pull-Up an DO ist
dran.
Deinen obigen Vorschlag habe ich schon umgesetzt, aus der Schleife kommt
der Controller bzw. die Karte nicht raus. Ich lese mir mal die
Bedienungsanleitung meines Logigports durch...
Mit mmc_init() hatte ich bis jetzt nur Probleme, wenn die Kabel zur
Karte zu lang waren, aber bei 120KHz dürfte das kein Problem sein.
Vielleicht mal andere Karten ausprobieren, Schaltung überprüfen sonst
hab ich keine Ahnung wieso die mmc_init() nicht durchläuft.
Hm über was wird die Karte mit Strom versorgt? Da können Peaks bis zu
60mA auftreten, und Ripple auf der Versorgungsspannung ist auch
schlecht...
Mach doch mal ein Foto von der Schaltung :)
Grüße Daniel
Hallo Daniel,
vielen Dank fuer die Tipps. Auf so einen Mist muss man erst einmal
kommen: Der SD-Kartenhalter von ALPS hatte an zwei Pads keinen
Kontakt... Da der groesstenteils geschlossen ist, kam man da nicht ran.
Das ganze hat lich jetzt eine 2GB-Karte gekostet, aber die sind ja
guenstig inzwischen.
Jetzt habe ich gerade meine erste Datei angelegt und beschrieben. Wenn
der Rest auch so gut laueft, waere das sehr cool. Danke fuer die
Bibliothek. :-)
Moin, ich bin grade dabei deine Bibliothek zu testen. Ich habe hier 3
SD-Karten liegen (1x 128MB, 1x 256 MB von toshiba und 1x 2GB von san
disk), allerdings gibt es Probleme beim Schreiben. Mein Prozessor ist
ein AT90CAN128, welcher mit 3,3V läuft und vom internem Takt versorgt
wird.
Hier eine genauere Fehlerbeschreibung:
-Lesen geht.
-Löschen von Dateien geht.
-Anlegen einer nicht vorhandenen Datei geht nur jedes 2. mal, wobei die
Funktion nie zurückkehrt, egal ob eine Datei auf der SD-Karte angelegt
wurde oder nicht.
-Schliessen einer Datei, bei der sich Daten geändert haben geht nicht,
es werden also nie Daten geschrieben.
Alle Schreibversuche auf die SD-Karten enden damit, dass der Prozessor
sich dauerhaft mit der SD-Karte unterhält, welcher Befehl übers SPI
läuft kann ich leider nicht sagen.
Die SD-Karten habe ich zwischendurch immer wieder mit Windows auf FAT32
formatiert. Die Einstellung SUPERFLOPPY habe ich sowohl gesetzt, als
auch nicht gesetzt probiert.
Eine genauere Beschreibung kann ich mangels JTAG-Interface leider nicht
geben.
mfg Emperor_L0ser
Hallo,
hast du irgendwo den Code geändert?
Wie rufst du die Funktionen auf?
Versuchst du zu überschreiben? Dann muss "OVER_WRITE 1" und "WRITE 1"
gesetzt sein.
Grüße Daniel
Moin,
ja ich habe den Code geändert, dies beschränkt sich allerdings darauf,
dass ich alle Variablendefinitionen aus den for-Schleifen entfernt und
an den Anfang der Funktion gepackt habe (ANSI-C99 Standard, mein avr-gcc
meckerte). Der AT90CAN128 ist von den Definitionen mit dem ATMega128
kompatibel, ich musste dort nichts ändern.
Ich verwende Version 0.5.3 und die Dateien, die dort nicht enthalten
sind (main.c, mmc.c und mmc.h) verwende ich aus 0.5.2. Aufrufen tu ich
nur die Funktionen, welche in der Beispiel-Funktion der main.c sind.
Write ist die ganze Zeit auf 1, sonst sind die Funktionen ja garnicht
vorhanden. OVER_WRITE habe ich sowohl gesetzt als auch ungesetzt
versucht.
mfg Emperor_L0ser
PS: ich verwende nicht die Makefile, meine Befehle, wie für alle meine
Projekte:
if avr-gcc -O2 -mmcu=at90can128 -DF_CPU=1000000 ./*.c
then
avr-objcopy -O ihex -R .eeprom a.out flash.hex
avrdude -p c128 -e -c pony-stk200 -U flash.hex
exit 1
fi
Hallo,
da liegt das Problem, es gibt Funktionen, da muss man noch Code
ergänzen, damit man die Definitionen nach oben schreiben kann.
Versuch mal dem avr-gcc "-std=gnu99" beizubringen. Dann einfach die
Original fat.c und file.c dann läufts...
Grüße Daniel
Ich hab es jetzt so gemacht, wie du gesagt hast und es läuft, schonmal
Danke dafür. Den ersten Teil deiner Antwort versteh ich nicht ganz. Ich
würd vor allem den Code gerne auch so schreiben, dass er ANSI-C Konform
ist, da ich ja nicht weiss, ob ich drei Jahren noch den GCC-Compiler
verwende.
mfg Emperor_L0ser
Ich bin es von C# und Java gewöhnt überall Variablen zu definieren und
Deklarieren, is schön bequem, aber is halt kein ANSI-C von 1986...
Eigentlich sollte jeder halbwegs gute Compiler auch ANSI/ISO-C99 können,
egal.
Hab grad den Code nicht vor Augen, aber man müsste Teile umschreiben,
damit man die Definitionen an den Anfang der Funktionen setzen kann.
Musst dir mal genau anschauen was da gemacht wird.
Grüße Daniel
Hallo Daniel,
ich habe die Lib zwar noch nicht getestet, scheint aber recht
interessant für mich zu sein.
Ich frage mich allerdings, wie ich den Inhalt des Directories weiter
verarbeiten kann. Eine Ausgabe auf die serielle Schnittstelle hilft mir
nicht weiter (ffls), da ich es auf einem direkt angeschlossenen Display
ausgeben möchte. Aus einem anderen Beispiel kenne ich zwei folgende
Funktionen:
* Ermittlung der Anzahl der Directory Einträge
* Ermittlung des Namens des x-ten Directory Eintrages
Können die beiden Funktionen mit den bereits vorhandenen gebildet
werden? Ich habe da nach Durchsicht Deiner Funktionen aber noch keinen
Ansatzpunkt gefunden. Wäre es aufwendig, diese beiden Funktionen noch
einzubringen? Ggf. könnte ich auch Tips gebrauchen, wie das anzugehen
wäre. Für mich wäre das aber recht zeitaufwendig, da ich in C noch nicht
so firm bin. Würde ich aber versuchen anzugehen.
Danke und Grüße
Ralf
Hallo Ralf,
wäre nicht sonderlich schwierig.
Mit den beiden vorhandenen Funktionen könnte man so etwas schon
realisieren, komme ich aber momentan nicht dazu.
Als Hinweis wenn du da selber schonmal was machen willst, "lsRowsOfClust
(unsigned long int start_sec)" geht durch alle Zeilen eines Clusters, ab
dem Sektor start_sec. "ffls(void)" geht dann durch alle Cluster eines
Ordners. Somit hat man beide logischen Strukturen abgearbeitet...
Will man jetzt wissen an welcher "Zeile" welcher Eintrag steht, müsste
man einen Zähler haben, der von lsRowsOfClust hochgezählt wird, bis man
an gewünschter Zeile ist.
Will man wissen wie viele Einträge es gibt, würde es reichen anstatt
einer Ausgabe einfach mit zu zählen, wie viele Einträge ausgegeben
werden würden.
Grüße Daniel
Hallo Daniel,
vielen Dank, Anzahl der Dateien (über ffls) sollte wirklich gar kein
Problem sein. Das andere muss ich mal sacken lassen :)
Werde ich mir die Tage mal anschauen.
Grüße
Ralf
Moin,
die Lib hat mir viel Arbeit erspart. Habe sie ohne größere
Schwierigkeiten auf einen MSP430 portieren können. Mir ist dabei nur
eine Sache aufgefallen. Die Initialisierung der FAT erfolgt ja in
Abhängigkiet ob "SUPERFLOPPY" 0 oder 1 gesetzt ist. Es ist aber schlecht
vorherzusagen ob in das fertige Gerät eine Karte eingesetzt wird, die
ein Superfloppy ist oder aber eine Partition enthält.
Habe die Initialisierung mal so geändert, das automatisch ermittelt wird
ob ein Superfloppy vorliegt.
//Prüfung ob man schon im VBR gelesen hat (0x6964654d = Medi)
11
if(secOfFirstPartition==0x6964654d)
12
returnfat_loadFatData(0);//Superfloppy liegt vor
13
else
14
//FAT-Daten aus dem ersten Sektor der Partition lesen
15
returnfat_loadFatData(secOfFirstPartition);
16
}
17
return(1);
Wenn man also eine Karte ausliest und man ist gleich im VBR, dann liest
man ja innerhalb dieses Abschnittes: "Datentr„ger entfernenÿ
Medienfehlerÿ Neustart: Taste drcken". An den Positionen 454 - 457
steht "Medi", was der Sektoradresse 1768187213 entspricht. Diese
Sektoradresse gibt es bei keiner bisher verfügbaren SD - Karte, weshalb
man damit auf Superfloppy prüfen kann.
mfg
Michael
Hallo Michael,
hab auch schon daran gedacht die Lib auf den MSP430 zu portieren.
Leider noch keine Zeit gehabt.
Hast Du vor, die an den MSP430 angepaßte Lib zu veröffentlichen ?
Noch einen schöne Tag
MfG
Siegmar
PS: Nochmals: Tolle Arbeit von Daniel !!!!!
Hallo zusammen,
das mit dem veröffentlichen für MSP wird wohl nix werden ^^
Anzupassen wären aber ja eigentlich nur die mmc low level Routinen.
Also die SPI Geschichten.
Hab leider keine Ahnung vom MSP daher schwer abzuschätzen wie viel
Arbeit das wirklich ist...
Grüße Daniel
Moin,
die meiste Arbeit haben die Routinen für das Lesen und Schreiben der
SD-Karte gemacht (wegen neu schreiben und so). Bei den FAT- und
Dateifunktionen habe ich erstmal nur die Void-Pointer (die ICC430
Version die ich nutze kann damit nicht um), die ganzen Zählvariablen
angepasst und natürlich die Funktionsaufrufe der Low-Level-Routinen
geändert. Eben um zu sehen ob es funktioniert. Und es funtkioniert.
Weitere Anpassungen sind sicherlich noch möglich, mach ich irgendwann
auch noch.
Michael
Hallo zusammen,
hier mal eine neue Version, gab da noch Bugs...
Zudem ist die SPI schreiben Routine schneller geworden.
Generell kompakterer Code.
Viel Spaß damit :)
Grüße Daniel
Hallo,
zuerst einmal ein Dank an Daniel dafür, dass er seinen Code hier
veröffentlicht hat. Ich möchte sein Beispiel nun bei mir lauffähig
bekommen, es funktioniert aber nicht. Auf der UART-Ausgabe sehe ich,
dass nach mmc_init() nichts mehr passiert, es muss also ein Fehler in
fat_initfat() auftreten. Ich verwende eine microSD Karte mit 128MB, die
ich per Windows als FAT formatiert habe. Wo müsste ich wohl ansetzen um
den Fehler zu finden?
Hallo,
wie ist denn die Karte am Controller angeschlossen?
Hast Du etwas am Code geändert?
Du siehst auf dem Terminal "Boot..." und das OK fehlt? Man sollte wenn
alles richtig initialisiert wird ja "Boot...OK" sehen. Wenn das OK fehlt
hängt sich das Programm tatsächlich beim Fat auslesen auf. Interessant
wäre da der Sektor 0 der Karte.
Oder Du könntest einfach mal probieren ob es FAT32 Formatiert klappt,
ich glaube bei Windows bedeutet nur Fat FAT16 und sonst halt FAT32.
Grüße Daniel
Da ich einen atmega328p verwende, habe ich die mmc.h verändert.
CLK von der Karte habe ich über einen HEF4050 mit SCK am µC verbunden,
DI auch über HEF4050 an MOSI, CS mit pull-up über HEF4050 an PB1 und DO
mit pull-up direkt an MISO. An anderen Stellen habe ich nichts im Code
verändert. Ja es erscheint wirklich nur Boot... . Im Anhang ein Bild vom
Sektor0, nach dem Versuch darauf zu schreiben.
Hallo,
also die Karte ist unpartitioniert. Versuch mal folgenden Code, damit
man feststellen kann ob es an der fat_initfat() liegt oder schon
woanders hakt.
1
voidmain(void){
2
chartmp[10];
3
4
uinit();
5
6
7
uputs((unsignedchar*)"\nBoot");
8
9
while(mmc_init()!=0){;}
10
11
uputs((unsignedchar*)"... ");
12
13
fat_loadFatData(0);// läd fat daten
14
15
16
ultoa(fat.rootDir,tmp,10);
17
uputs(tmp);
18
uputc(' ');
19
20
utoa(fat.secPerClust,tmp,10);
21
uputs(tmp);
22
23
}
Jetzt müsste wenn alles funktioniert, "Boot...2 2" zu sehen sein.
Wenn dem so ist muss ich mir die fat_initfat() nochmal genauer
anschauen.
Wenn nicht, liegt das Problem irgendwo ganz anders. Da würde ich eher
auf ein Hardware Problem schließen.
Im Datenblatt von dem HEF4050 steht nichts von Versorgungsspannung ab 2
Volt wie bei dem HC4050, was bei niedrigeren Frequenzen vielleicht noch
klappt aber dann nach der Karten Initialisierung mit vollem SPI speed
nicht mehr...
Grüße Daniel
Als Ausgabe erhalte ich "Boot..." und manchmal "Boot... 0 0" und einmal
wurde sogar die txt-Datei erstellt, es liegt also an der Hardware. Eine
2Gb Karte habe ich damit wohl schon zerstört, zumindest reagiert Windows
nicht mehr, wenn ich die Karte einlege. Aber das die Karte
unpartitioniert ist verstehe ich nicht, habe es im Arbeitsplatz per
Rechtsklick und dann auf Formatieren formatiert. Ich werde dann mal die
74HC4050 von reichelt bestellen und alles neu aufbauen. Schonmal danke
für die schnelle Hilfe.
Mir ist noch keine einzige Karte kaputt gegangen bei meinen Tests. Ich
nehmen aber auch immer sofort den Strom weg, wenn was unvorhergesehenes
passiert.
Unpartitioniert ist ja nicht unformatiert. Keine Ahnung warum Windows
mal ne Partition erstellt und mal nicht. Glaube bei kleineren Karten
wird nicht partitioniert und bei größeren schon.
Du könntest aber auch mal den SPI speed runter setzen und schauen ob es
dann mit deiner Hardware stabiler läuft.
Einfach in der mmc.c in der Funktion mmc_init () die Zeilen
1
//SPI Bus auf max Geschwindigkeit
2
SPCR&=~((1<<SPR0)|(1<<SPR1));
3
SPSR=SPSR|(1<<SPI2X);
auskommentieren.
Bei deiner Karte die nicht mehr funktioniert, könnte es sein das die
mehr als 3,3 Volt abbekommen hat? Mach doch mal ein Foto von der
Schaltung :)
Grüße Daniel
Hallo mal wieder!
Ich bastel im Moment wieder mit dem SD-Code rum. Soweit alles in
Ordnung. Allerdings ist file.seek bei mir immer Null. Das darf aber
eigentlich nicht sein. Mein Code:
########################################################################
#
int main(void) {
char *tag;
char *value;
char s[10];
lcd_init();
lcd_clear();
sd_init();
lcd_clear();
tag = malloc(30);
value = malloc(30);
char mfile[] = "testdat.txt";
fat_str(mfile);
ffopen(mfile);
// Länge der Datei ausgeben
lcd_string("L: ");
lcd_string(itoa(file.length, s, 10));
lcd_set_cursor(0,1);
// Position ausgeben
lcd_string("S: ");
lcd_string(itoa(file.seek, s, 10));
_delay_ms(2000);
while (file.seek <= file.length) {
tag[0] = '\0';
value[0] = '\0';
lcd_clear();
tpx_read_tag(tag, value);
lcd_string("T: ");
lcd_string(tag);
lcd_string("; S: ");
lcd_string(itoa(file.seek, s, 10));
lcd_set_cursor(0,1);
lcd_string("V: ");
lcd_string(value);
_delay_ms(1000);
}
ffclose();
while(1);
return 0;
}
########################################################################
#
tpx_read_tag ist eine funktion von mir, die eine Art pseudo-xml
realisiert nach dem Muster <tagname=wert>.
Ich brauche file.seek, damit das Auslesen irgendwann mal aufhört.
Noch etwas, ich bekomme warnings:
"./sd/fat.c:96: warning: left shift count >= width of type"
Bis denn dann,
StrangeMan
PS: Am Software-SPI wäre ich auch sehr interessiert! =)
Hallo,
also so ist file.seek nicht gedacht.
Es wird beim lesen garnicht verwendet. Wenn du bis zum Datei Ende lesen
möchtest ist die schnellste Variante:
1
unsignedlongintseek=file.length;
2
3
do{
4
5
codezumlesen...
6
7
}while(--seek);
Da so nur geprüft wird ob seek==0 ist als Abbruchbedingung...
Zu dem angesprochenen warning, das hab ich auch, allerdings "nur" beim
avr-gcc, dem normalen gcc macht das nix. Also hat keine Probleme gemacht
bei mir. Und den left shift muss man so machen...
Grüße Daniel
Und wenn ich in dem Moment gar nicht weiß, wo sich der "Cursor" in der
Datei befindet?
Hmm, da bleibt mir wohl nichts übrig als mir eine globale Variable zu
machen, die mitloggt, wo ich bin.
Wie wäre es mit der Variablen seek aus meinem Beispiel?
Ich habe extra darauf verzichtet in ffread() eine 32 Bit variable wie
file.seek bei jedem einzelnen Byte das gelesen wurde zu ändern...das
würde bremsen! Besser ist es da die Laufindex Variable (aus dem Beispiel
eben, seek) beim Aufruf von ffread() zu benutzen.
Wozu genau willst du denn die exakte Position in der Datei wissen?
Und wie gesagt, was spricht gegen die Variable seek?
Grüße Daniel
Hmm, ich hab ein Menüsystem, was auf Basis oben genannter
Pseudo-XML-Tags die Menüeinträge ausließt. Wenn ich eine Funktion habe,
die nur einen Tag auslesen soll, dann hat die ja keine Ahnung, wo in der
Datei sie auszulesen beginnt, wenn ich sie aufrufe. Sie darf aber
dennoch nicht über das Dateiende hinauslesen. Wenn ich das so amche, wie
im Code oben, dann kann es ja sein, dass sie erst beim 100ertsten Byte
anängt zu lesen, weil der "Cursor" da grade war. Dann würde sie 100
Bytes üebr das Dateiende hinauslesen. Was da bei rauskommt habe ich
schon gesehen... Zufallsdatan - mehr oder weniger.
Aber ich habs jetzt so gelöst, dass ich einfach mitlogge, wo ich bin.
Bei jedem ffread() oder ffseek() aktualisiere ich meine globale Varable
eben.
Das Geschwindigkeitsproblem ist natürlich ein Argument. Aber eventuell
kann man so eine Seek-Variable als Compilerschalter mit einbauen. Dann
kann man's aktivieren, wenn es benötigt wird. Ich denke, für komplexere
Dinge ist sowas schon von Nöten.
StrangeMan
Ok, überlege ich mal wie man sowas elegant machen kann.
Du könntest ja aber einfach file.seek benutzen anstelle deiner globalen
variable. Wie das dann mit der Geschwindigkeit aussieht müsste man mal
sehen. ffseek() updatet dir file.seek ja auch wenn du vor oder zurück
spulst. Kleines Beispiel:
Hallo mal wieder.
Ich hab die mcc.c/mcc.h von Ulrich Radig rausgekramt und den
Software-SPI-Modus von ihm wieder übernommen. Allerdings ... naja, es
klappt nicht, und ich weiß nicht, obs an meiner Hardware oder am Code
liegt. Ich hab meine Version der mcc.c mal angehängt. Eigentlich kann
man ja nichts falsch machen. Offensichtilich aber doch...
StrangeMan
Neue Version !
Überarbeitete mmc.c und Optimierung des Codes.
Jetzt auch Multiblock Operationen möglich. Wird allerdings nicht von
allen Karten unterstützt, daher optional als define wählbar.
Neuere Doku wird nachgereicht.
Wird wie immer hier nachzulesen sein:
http://www.mikrocontroller.net/articles/AVR_FAT32
Grüße Daniel
Daniel,
ich hab mir heute mal die neue Version deiner Lib zu Gemüte geführt. Wie
auch die alten Versionen funktioniert das auf einem zur Zeit in der
Mache befindlichen Alleskönner-Board wie geschmiert. Super Arbeit!
Und - wie bereits letztes Jahr - ich hab mal wieder ein paar Ideen, die
die Lib noch besser machen könnten. Für mich natürlich :-)
1) Sinnvolle Rückgabewerte
Viele Methoden geben unsigned chars für Statusinformationen zurück.
Sowas in etwa:
1
if(2==ffopen("TEST TXT")){...}
Hier würde ich mir defines wünschen, die eben diese Statusinformationen
sprechend bezeichnen. Sowas z. B.
1
#define MMC_FILE_NEW 2
2
if(MMC_FILE_NEW==ffopen("TEST TXT")){...}
Gibt es eigentlich eine Doku für diese Return-Values?
2) Uart-Funktionen per Config einstellen
Das hatte ich mir ja schon oben gewünscht, da ich ansonsten jedesmall
die Sourcen ändern muss.
3) Status-Signale der SD-Card
Bei den meisten Kartenslots kann man neben den wichtigen Pins auch
auslesen, ob eine Karte eingelegt ist und ob diese schreibgeschützt ist.
Wär doch schön, wenn wie die Lib von Roland Riegel, das auch
berücksichtigt werden könnte.
Alle Config-Optionen in eine separate Config-Header-Datei geschrieben
sieht dann so aus, wie im Anhang zu finden. Die SPI-Pins etc. ziehe ich
mir aus einer globalen Hardware-Header für SPI. Die Defines für die
Statusinformationen könnten wohl auch woanders hin.
cu, Michael
Hallo,
bin immer offen für Anregungen :)
-1.) Mich hat es Tatsache auch schon öfters genervt das man einer 2
nicht ansieht was es genau bedeutet... werde ich ändern.
Störend ist nur, dass z.B. folgendes "define TRUE 1" 2 Byte Ram frisst
wenn man "TRUE" irgendwo im Code nutzt. Mir war nie die Idee gekommen
"define TRUE '1'" zu machen :) ist dann nur ein 1 Byte ...
-2.) Da fällt mit keine tolle Lösung ein, na ja mal sehn...
-3.) Ich hab so nen Kartenslot nicht, daher kann ich das schlecht
testen, müsste mir mal so nen Slot besorgen :)
Software SPI möchte ich dann auch noch mich rein packen ins nächste
Release.
Grüße Daniel
Moin Daniel,
> Störend ist nur, dass z.B. folgendes "define TRUE 1" 2 Byte Ram frisst> wenn man "TRUE" irgendwo im Code nutzt. Mir war nie die Idee gekommen> "define TRUE '1'" zu machen :) ist dann nur ein 1 Byte ...
Ist dem wirklich so? Bis heute dachte ich, dass defines nur durch den
Präprozessor verwendet zum ersetzen herangezogen werden und erst danach
der compiler einspringt...
Zum Uart:
Für dich relevant sind ja nur 3 Infos zum Uart. Include-Statement,
uputs, uputc. Ich (als Freund der #defines würde das dann wieder per
config-Option lösen. Also:
1
#define UART_INCLUDE /path/uart.h
2
#define UART_UPUTS uputs
3
#define UART_UPUTC uputc
und dann im Code die ensprechenden defines statt der echten Namen
verwenden.
Zu 3 - Status Info:
Hier müsste man überlegen, wie weit man wirklich dies durchgängig
implementieren will. Reicht es, wenn man entsprechende Methoden zum
Abtesten anbietet, den eigentlichen Test aber dann den Nutzer
durchführen lässt? Oder nur bei mmc_init()? Oder sollen alle Lese- bzw.
Schreiboperationen jeweils isAvailable4() oder isProtected() aufrufen?
Letzteres eher nein, so würde ich denken.
cu, Michael
Hallo,
hier mal ein kleines Update. Der Code ist nur auf anständige Return
Werte umgestellt. Keine Funktionalen Änderungen.
>Ist dem wirklich so?
Ich dachte immer das wenn man "#define KONSTANTE 1" macht, wird das als
Integer behandelt bei der Erzätzung im Code durch den
Präprozessor...deshalb hab ich die defines jetzt einfach mal alle als
chars gemacht, kann ja nicht schaden ^^
Zum Uart, zufriedener jetzt ?
Hast Du so einen Slot und wärst eventuell bereit die Funktionen zu
schreiben und testen? Ich nehme die dann in die Lib auf. Stimme da
nämlich bei Deine Überlegungen zu.
@Winne
Das müsste man ja dann als struct machen, und ich weiß nicht mehr warum,
aber das ist wohl nicht so toll...
Vielleicht weiß da ja einer warum ?!?
Grüße Daniel
Moin Daniel
> hier mal ein kleines Update. Der Code ist nur auf anständige Return> Werte umgestellt. Keine Funktionalen Änderungen.
Wunderbar. Genau so etwas meinte ich. Wie sieht es bei ffopen im
OVERWRITE Modus aus? Wird hier auch OPENED_TO_WRITE zurückgeliefert?
> Zum Uart, zufriedener jetzt ?
Fast :-) Die Defines wie auch eine globale COnfig-Datei sind klasse.
Fehlt nur noch, dass die Quellen mmc.c und file.c auf die neue
uart-syntax angepasst werden :)
> Hast Du so einen Slot und wärst eventuell bereit die Funktionen zu> schreiben und testen? Ich nehme die dann in die Lib auf. Stimme da> nämlich bei Deine Überlegungen zu.
Ich hab so einen Slot und ja, ich könnte dies ausprobieren und
entsprechend implementieren. Das ganze würde dann über zwei Funktionen
in mmc.h / mmc.c implementiert werden. Nämlich:
- u08 mmc_present()
- u08 mmc_protected()
Diese kann der User nach belieben selber aufrufen. Ausserdem werden
diese in mmc_init() mit aufgenommen. Sollte keine Karte vorhanden sein
bzw (bei write-Funktionalität) diese schreibgeschützt sein, so werden
entsprechende Status-Codes zurückgeben. Das ganze wird natürlich per
#define abschaltbar :-) Und je nachdem, ob write-Support drin ist oder
nicht, werden nur die erforderlichen Methoden kompiliert.
Da ich nur am WoE zum Testen komme kann das ganze aber doch 2 bis max. 3
Wochen dauern. Geht halt nicht schneller
cu, Michael
Erstmal danke für die Lib, funkt sehr gut bei mir. Nur eines, was es
vielleicht Anfängern erleichtern könnte:
In der mmc.h steht:
#if defined (_AVR_ATmega16_)
#define SPI_DI 6 //Port Pin an dem Data Output der MMC/SD-Karte
angeschlossen ist
#define SPI_DO 5 //Port Pin an dem Data Input der MMC/SD-Karte
angeschlossen ist
...
Der Satz "Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist
" drückt, denk ich, das Gegenteil von dem aus, was er sagen soll. Weil
SPI_DI ("Data in") der MOSI pin ist, also der Data Output vom Master und
nicht von der Karte. Vice versa für SPI_DO.
Vielleicht kann man einfach MOSI/MISO/SCK/.... in die Comments
schreiben.
Nur so als Vorschlag.
Danke nochmal,
mik
Naja, ich dachte da ist der DataIn der Karte gemeint. Aber MOSI/MOSI
wäre sicherlich eindeutiger.
Eine globale Configdatei würde ich auch befürworten. Ich habe sie mir
für mein Projekt selbst angelegt, weil ich da sehr viele verschiedene
Defines habe, die ich zentral editieren können will. Wenn man auch in
diesem Code hier eine globale Configdatei macht, ließe sich deren
Include-Anweisung einfach rauskommentieren um eine eigene Configdatei zu
erwenden.
StrangeMan
Hallo, zusammen.
@Michael Z. (incunabulum)
Ja wäre cool wenn du das so machst mit dem Slot. Eilt auch nicht so ...
@StrangeMan (Gast)
Die mmc-0.5.5.1.zip hat schon eine solche config.h
@ Michael M. (mikmik)
Du benutzt nicht die Version mmc-0.5.5.1.zip ?
Da ist zwar die Dokumentation in der mmc.h noch nicht auf MISO/MOSI usw
umgestellt aber mit den defines ist es einfach übersichtlicher
Man könnte das noch etwas verkürzen:
1
unsignedcharffexists(unsignedcharname[]){
2
returnfat_loadFileDataFromDir(name);
3
}
Und als Abfrage:
1
if(TRUE==ffexists((unsignedchar*)"MAIN C "){
2
3
irgendwasmachen
4
}
Da das ja aber eigentlich nur eine Zeile ist und man sich wenn man das
direkt machen würde wie z.B :
1
if(TRUE==fat_loadFileDataFromDir((unsignedchar*)"MAIN C "){
2
3
irgendwasmachen
4
}
auch eine Funktionsaufruf spart hatte ich das nicht extra geschrieben :)
Ist zwar fragwürdig ob man bei sowas sparen muss aber egal.
Grüße Daniel
Ach ja, was mir da noch einfällt,
wenn man im Überschreibenmodus eine Datei öffnet bekommt man auch
OPENED_TO_READ zurück. Es gibt die Datei ja schon die man überschreiben
möchte. Wenn man sich einmal für OVER_WRITE entschieden hat, kann man
wild in der Datei rumschreiben...
Grüße
Moin Daniel,
hier also die entsprechende Erweiterung deiner Lib. Status-Pins (card
present, card protected) werden nun berücksichtigt, so entsprechend in
config.h aktiviert. Die wichtigen Änderungen meinerseits findest du nach
dem Tag // mz:
Die eigentliche Konfiguration erfolgt in mmc.h unten. Dort werden die
Pins etc. entsprechend gesetzt. Das ist fast 1:1 von Roland Riegel
kopiert. In mmc.c sind dann die entsprechendne Methoden definiert und in
mmc_init() eingebunden.
Anmerkungen:
0) Ich habe einige zusätzliche Return-Werte mittels Define gesetzt. Das
macht die Lib imho lesbar. Fehlt nur noch die Doku :-)
1) FALSE sollte immer (int) 0 sein. Ansonsten ist ein Test über
if(someBoolMethod()) nicht möglich, sondern es wird immer ein expliziter
Vergleich if(true==...) benötigt.
2) defines: Ich habe mal alle Defines umgeändert, so dass diese immer
als Präfix MMC_ aufweisen. Dies ist gängige Syntax, da man hierdurch im
Code zumindest erraten kann, welches Define für was herangezogen wird.
Oder wüsstest du, woher WRITE kommt, so diese Directive in main()
vorkommt?
2b) OPENED_TO_READ und OPENEND_TO_WRITE sind imho nicht ganz korrekt.
Siehe die Problemtatik bem überschreiben. Ergo habe ich diese wieder
unbenannt zu MMC_FILE_NEW, MMC_FILE_EXISTS. Das trifft die Tatsache
besser, denke ich.
Comments?
cu, Michael
Hallo,
ja sieht soweit gut aus.
In der SdCard.h ist das c++ ? Da steht was von namespace ?!?
Hatte jetzt noch nicht die Zeit mir alles mal genauer zu Gemüt zu
führen, mache ich aber heute Abend.
Zu den defines,
FILE_NEW und FILE_EXISTS find ich gut.
Allerdings hast du ja jetzt alle defines in MMC_xxx umbenannt. Bringt
also genau so viel wie gar kein Präfix, oder hab ich da was falsch
verstanden? Außerdem gibt es defines die in allen Dateien vorkommen wie
z.B. MMC_WRITE (alias WRITE) auf was sollte man sich da jetzt festlegen?
Werde das aber aufgreifen und mal sehen ob man das nicht noch etwas
bessert ordnen kann.
Generell, wenn man etwas in Großbuchstaben sieht ist es ein define und
die sind immer in der config.h, das ist doch auch schonmal was :)
Danke für die Hilfe und Mitarbeit.
Grüße Daniel
Moin Daniel,
ja, da ich komplett mit C++ entwickel, ist die SdCard.h ein einfacher
Wrapper für CPP. Das kannst du also ignorieren. Dieser packt die ganze
MMC-Funktionen in einen eigenen Namespace und verwendet eine
Methodenbennenung, wie ich sie sonst verwende. Also Camel-Case anstatt
Unterstriche.
> Zu den defines,> Allerdings hast du ja jetzt alle defines in MMC_xxx umbenannt. Bringt> also genau so viel wie gar kein Präfix, oder hab ich da was falsch> verstanden?
Ich glaube ja. Nem mal an, dass du zwei Libs verwendest. a) Deine MMC
und b) eine EEPROM Lib. Beide definieren ein #define WRITE. Solltest du
nun in main() beide Libs importieren, so hast du das Problem, dass WRITE
aus der mmc oder der EEPROM lib kommen kann. Weiterhin kann es sein,
dass diese auch noch mit unterschiedlichen Werten definiert ist. Und
dann?
So, wie ich deine Lib sehe, wird das Problem nicht auftreten, da eben
config.h nur von den mmc-headern und sourcen und nicht von "extern"
included wird. Dennoch finde ich es für den Fall, dass dies aus
"Dummheit" doch jemand machen sollte, eine gute Idee, die Quelle durch
das MMC_ Präfix deutlich zu machen.
> Außerdem gibt es defines die in allen Dateien vorkommen wie> z.B. MMC_WRITE (alias WRITE) auf was sollte man sich da jetzt festlegen?
Äh, das Präfix MMC bedeutet (imho) nicht, dass diese aus der MMC.h
stammt, sondern dass es ein define aus deiner mmc-lib ist. So hab ich
mir das jedenfalls gedacht :-)
> Generell, wenn man etwas in Großbuchstaben sieht ist es ein define und> die sind immer in der config.h, das ist doch auch schonmal was :)
Jenau :)
> Danke für die Hilfe und Mitarbeit.
Ich will ja auch was :-) Nämlich die Funktionen die ich brauch und zwar
ohne manuelles Merging bei folgenden Versionen
cu, Michael
Hi,
ich wollte eben die neuste Version der SD-Kartenroutine ausprobieren und
bin erschrocken!
Warum ist eine UART Routine mit in das Gefecht eingewoben worden?! Macht
das Sinn?
Ich verpacke doch auch nich in eine UART-Routine ein I²C, nur weil ichs
kann.
Das is doch am Thema vorbei, ober sehe ich das Falsch?
Gruß
Hallo,
bin immer noch nicht dazu gekommen mir alles anzusehen, aber so viel
wurde ja auch nicht geändert...
>Warum ist eine UART Routine mit>in das Geflecht eingewoben worden?!>Macht das Sinn?
Wie meinst du das ?
Es sind ja in der config.h nur defines dazugekommen, mit denen man seine
eigene uart lib einbinden kann...
Grüße Daniel
Aber warum generell UART in einer SD-Karten-Routine?
Soll diese Routine nicht nur und ausschließlich für SD-Karten sein?
Das bläht das ding nur unnötig auf und wer eine UART überwachung haben
will, der kann das doch auch selber, z.b. in seine main.c, schreiben.
Ich wundere mich bloß warum in der file.c in zeile 210 plotzlich der
dateiname ausgegeben werden soll. wenn ich an meinen UART-Pins aber
andere bausteine angeschlossen hab als ein max232, dann kriege ich
dadurch probleme!
deswegen: warum diese feste UART einbindung?
Stimmt schon, müsste nicht unbedingt rein, aber das ist als Beispiel
gedacht.
Die meisten werden wohl den UART angeschlossen haben um sich z.B. mal
Debug Ausgaben zu machen, oder für Bootloader.
Mach "MMC_SMALL_FS TRUE" und du bist den UART los.
Funktionen wie ffls, also anzeigen von Dateien eines Verzeichnisses,
leben nunmal von der Ausgabe auf eine Anzeige, in diesem Fall die
UART...
Grüße Daniel
Man könnte die Dateinamen mit der Anzahl n und die Größe in zwei Arrays
schreiben, z.B. dateien[n*8], groesse[n] und die zwei per Pointer
zurückgeben.
Dann kann man, wie man will, sich sie per UART, LCD oder sonstwie
ausgeben lassen:
1
for(inti=0;i<8,i++)uart_putc(dateien[i]);
wäre der erste dateiname
1
for(inti=11;i<19,i++)uart_putc(dateien[i]);
wäre der zweite dateiname
usw.
die größe natürlich äquivalent.
oder man schreibt die funktion so um, daß´sie immer nur einen dateinamen
zurück gibt, beim nächsten aufruf den zweiten, ... nachdem der letzt
ausgegeben wurde eine NULL zurückkgibt.
Für die Dateigröße eine zweite funktion, die das selbe macht.
Damit wären die speicherfressenden arrays von meiner ersten idee
umgangen und man kann die rückgabewerte auf LCD, UART etc ausgeben.
grußm
matze
Hm, je mehr ich darüber nachdenke je besser gefällt mir das mit dem
auslagern der UART.
Das auslagern würde ja auch das Problem lösen, an die mitgelieferte
uart.c/uart.h gebunden zu sein. Man könnte dann ja einfach seine eigene
in der main.c includen...
Hallo Daniel,
erstmal danke für die tolle Lib von dir. Habe sie getestet, sie
funktioniert wunderbar.
Nun hätte ich gerne eine ganz kleine Ergänzung in der mmc.h:
statt "#if defined (_AVR_ATmega32_)"
#if defined (_AVR_ATmega32_) || (_AVR_ATmega16_)
weil ich mich erst gewundert habe, wieso es zu fehlern bei meinem
ATmega16 kam.
Weiterhin hätte ich die Frage, ob du mir sagen kannst, wieviele Zyklen
der "ffclose()"-Befehl inklusive der Unterfunktionsaufrufe braucht. Ich
würde das ja selber machen, leider kann ich aber mit assembler nichts
anfangen (die Sprünge in die Unterfunktionen usw. erkenn/versteh ich
nicht).
Die Frage habe ich, weil ich derzeit Daten auf die Karte schreibe
(ffwrites()), und erst bei Knopfdruck den ffclose()-Befehl ausführe.
Wenn aber die Spannungsversorgung zusammenbricht, möchte ich auch
ffclose durchführen (damit ich die Daten auf der Karte sehe) und daher
brauche ich die Zyklenzeit zur Berechnung meiner Kondensatoren in meinem
Spannungsregler.
Hoffe das passt hier hin, gehört ja zu deiner Lib, aber hat halt nicht
direkt damit zu tun.
Gruß
Arne
Guten Morgen,
muss erstmal ein gorßes Lob an Daniel los werden, die Lib läuft bei mir
einwandfrei! Mit den Libs von Roland Riegel etc. bin ich hingegen nicht
zurecht gekommen...
Habe aber trotzdem noch eine Frage:
Wäre es möglich, abzufragen wie viel Speicher auf der SD Card nocht
vorhanden ist? Werde mir gleich im Code von Roland mal ansehen wie er
das abfragt.
Gruß,
Patrick
Hallo zusammen,
@ Arne Z. (Gast)
Das mit dem define, wird aufgenommen, kein Problem.
Die genaue Taktzahl ist schwer zu bestimmen, da sie von mehreren
Parametern abhängt.
Wenn z.B. 256 Cluster am Stück frei waren und du bei ffclose alle
beschrieben hast (aber nicht darüber hinaus !) müssen die ja noch
verkettet werden.
Das macht dann zwei Schreiboperationen von 512 Byte Blöcken in der FAT
aus. Dazu kommt noch das erneute Suchen der Datei im Verzeichnis, was je
nach Größe des Verzeichnisses und Lage der Datei im Verzeichnis immer
unterschiedlich lange dauert. Dann noch schreiben von 512 Bytes um den
Datei Eintrag zu updaten.
Die Zeit für die Schreiboperationen ist nicht wirklich das Problem, aber
die Zeit für das suchen von Dateien schon...
Am besten du ermittelst das Empirisch indem du einen Timer laufen lässt
und verschiedene Szenarien durchspielst.
@Patrick Franken (helipaddi)
Ja ist möglich, man müsste ja nur alle leeren Cluster Nummern in der FAT
zählen, diese mit der Anzahl der Sektoren/Cluster multiplizieren und
schon hätte man das Ergebnis.
Hab momentan leider nicht so viel Zeit, aber werde ich einbauen.
Oder du schaust mal wie weit du kommst und schreibst das, dann nehme ich
es auf :)
Die Funktion "unsigned long int fat_getNextCluster(unsigned long int
oneCluster)" ist da dein Freund.
Spätestens nächste Woche hab ich massig Zeit.
Grüße Daniel
(nun nichtmehr Gast, sondern angemeldet)
Hallo Daniel,
danke für deine Antwort. Dann werde ich wohl mal verschiedene Szenarien
bauen und die Zeiten überprüfen, so dass ich meinen Kondensator
berechnen kann.
Und dann hab ich noch zwei Fragen: und zwar habe ich derzeit eine
Funktion, die vor main() läuft, die die Datei öffnet und ans Ende geht.
Dann wird in der main() alle 1sek bis 8 Stunden in der Datei einen
Messwert aufgezeichnet. Erst wenn ich den Stop-Knopf drücke, wird
ffclose ausgeführt. Gehen meine Daten verloren, wenn ich zu lange kein
ffclose ausführe, oder aktualisiert ffclose nur das fat und verkettet?
(also die Daten sind physisch auf der Karte, nur man sieht sie nicht)
Weiterhin gibt es eine Methode, wenn ich Daten geschrieben habe, aber
nicht ffclose ausgeführt habe, die SD-Karte zu "reparieren", so dass
meine Daten sichtbar werden?
Danke schonmal,
Arne
Hallo,
ja die Daten sind physikalisch auf der Karte. Allerdings nur in 512 Byte
Blöcken.
Wenn du weißt, es passiert 8 Stunden nix, wäre ein ffclose zwischendurch
ja nicht so schlimm.
Soweit mir bekannt ist, gehen Dateisysteme davon aus, dass Cluster die
zu einer Datei gehören immer aufsteigend gesucht werden. Daher habe ich
es so gemacht, dass die Datei schon beim öffnen Physikalisch angelegt
wird, also mit Dateieintrag und Startcluster. Die freien Cluster die für
die Datei dann verkettet werden, werden ab dem Startcluster der Datei
gesucht.
Das bietet den PC Data-Recovery Tools die Möglichkeit der Datenrettung.
Obwohl so einmal mehr der Dateieintrag geschrieben werden muss, am Ende
ja auch wegen der Dateigröße. Funktioniert allerdings nur zuverlässig
bei einer Datei...
Grüße Daniel
Hallo Daniel!
Erst mal hochachtung vor deiner Arbeit. Hab den Code für den
ADUC7024(ARM) portiert.Nach fast 2 Wochen teilweise frustrierender
Arbeit,Schuld sind die Arschlöcher von SD-Karten Herstellern, die keine
vernünftigen Datenblätter herausgeben, läuft das Ganze nun einigermaßen.
Allerdings sind da 2 Punkte, die mich noch etwas beschäftigen:
1.)Nach dem Schreiben eines Sektors(Zeit: ca. 2ms) gibt die Karte
innerhalb eines Bytes 0xE5 (Daten akzeptiert) aus.Danach geht Data out
der SD auf 0(busy) und bleibt dort für gut 5ms.Während dieser Zeit,kann
man keine Kommandos an die Karte senden,sondern muß warten, bis Data out
1 wird. Damit komm ich auf einen Zyklus von ca. 7ms für 512Bytes = ca
70KB/s.Nicht gerade berauschend.Ich hab dann noch eine SanDisk Ultra II
2GB probiert, die ging dann mit ca. 110KB/s(busy-Phase war deutlich
kürzer). Frage: wie kommen die Leute auf 150KB/s und mehr? Mach ich was
falsch?
2.)Es gibt bei mir das Problem, wenn ich immer das selbe File öffne,
Daten hinzufüge und wieder schließe,dass auf einmal falsche Sektoren
beschrieben werden,und das File für den PC unleserlich wird.
Interessanterweise tritt das erst bei einer Filelänge > 0x1000000 (16MB)
auf. Mit 1x öffnen, schreiben und schließen hab ich aber auch schon 50MB
files erzeugt,die der PC lesen konnte. Nach einem rudimentären Debug
könnte der Fehler in ffseek liegen,kanns aber noch nicht genauer
festmachen.
Gesehen hab ich in diesem Tread noch nichts,was auf ein solches Problem
hinweist.Möglicherweise ist's aber auch noch nicht aufgefallen,oder ich
hab beim portieren Mist gebaut.
Ach ja, die verwendete Version ist 5.4,die Karten sind FAT16 formatiert.
Grüße Gebhard
Hallo,
@ geb (Gast)
Hast du die Karte über SPI angeschlossen? Wenn ja mit welcher
Geschwindigkeit? Ich habe hier MMC Karten (die sind meist bisschen
schneller als SD) die machen 200KBytes/sec schreibend und 270KBytes/sec
lesend. Das bei 10 mhz SPI Takt und im nicht überschreiben Modus.
Bei der Version 5.4 gab es tatsächlich ein Problem in ffseek im
Zusammenhang mehrfachem anlegen von Dateien. Nimm am besten die 5.5.1
von hier
http://www.mikrocontroller.net/attachment/58218/stable-mmc-0.5.5.1.zip
,ist aber auch schwer zu sagen ob da nicht vielleicht doch auch beim
portieren was falsch gelaufen ist. Wenn du magst, poste doch mal deine
geänderten Routinen, dann kann man mal drüber schauen :)
So schönen Wahl Sonntag noch :)
Hallo!
Mir ist aufgefallen, dass, wenn ich innerhalb eines Interrupts eine
Datei öffne, sich das Programm nach dem Interrupt resetet. Komisch.
Ich hab's umgangen, indem ich einen Funktionszeiger eingerichtet habe,
der im Interrupt auf die auszuführende Funktion (die, die die Datei
öffnet) gesetzt wird. Das Hauptprogramm prüft in einer Endlosschleife
verschiedene Dinge, und führt dabei immer mal diese Funktion aus. Damit
verlagere ich dieses Öffnen ins Hauptprogramm und die Probleme sind weg.
Ich hab aber keine Ahnung, warum sich der AVR da resetet... Irgendwas
mit dem Stack oder so? Wie gesagt, das reseten passiert am Ende der ISR.
StrangeMan
Hallo Daniel!
Mein Geschwindigkeitsproblem liegt an der langen busy Phase der SD
Karte.
Reine Schreibdauer ca. 2ms/sektor, busy ca. 5ms(lt.
Oszilloscope).Sicher,die max. 3,24Mhz SPI Takt sind auch nicht gerade
berauschend, da hat sich Analog Device nicht gerade mit Ruhm bekleckert.
Ich werd jetzt mal die Vers. 5.5.1 portieren, und wenn das wirklich
stabil läuft,hab ich die Idee, das fread und fwrite als Statemachine
auszuführen und die SPI interruptgesteuert zu verwenden. Damit könnten
diese Funktionen im Hintergrund laufen und würden nur mehr minimale
Prozessorzeit beanspruchen(die meiste Zeit wird ja jetzt eigentlich nur
gewartet).
Grüße Gebhard
Huhu,
Ich habe nun mal gemessen, wie lange ein ffclose() dauert. Dabei kam ich
auf Werte zwischen
216.664 und 378.200 Takte (bei ATMega 16 @ 16MHz).
Im Durchschnitt lag ich bei 260.000 Takten (der große Wert war wohl ein
statistischer "Ausrutscher" ^^).
Die Werte änderten sich zwar immer, aber ob die Karte nun voll war, oder
komplett leer, hatte irgendwie keinen Einfluss.
Daniel, weißt du zufällig, ob das realistische Werte sein können?
Hast du evtl. noch eine Idee für einen "Worst Case" Fall?
Gruß
Arne
Hallo!
Hab die Vers. 5.5.1 für ADUC702x(ARM7) portiert und läuft soweit
fehlerfrei.
Weiters hab ich in mmc.c eine Unterstützung für SDHC Karten eingebaut
und die Schreibperformance durch verkürztes warten auf das Ende der
"busy" Phase verbessert.
Mit den SanDisk Ultra-Karten(SD 2GB und SDHC 4GB) kann ich jetzt doch
150kB/s schreiben, bei 3,24 MHz SPI clock(gähn).
Ich stell mal mein mmc.c hier rein zum testen.
Grüße Gebhard
Hallo zusammen.
@ Arne Z. (theich)
Also ich müsste da selbst mal ein bisschen messen um das zu sehen. Nur
rein theoretisch müsste die Zeit um eine Datei zu finden abhängig von
der Anzahl der Dateien sein die in dem Verzeichnis sind. Je mehr Dateien
umso länger die Such Zeit.
Sagen wir mal man kann mit 200 KBytes/s lesen, das macht dann ungefähr
400 Sektoren und somit 6400 Datei Einträge (weil 16 pro Sektor). Ist die
gesuchte Datei jetzt die letzte, also Datei Nummer 6400, dauert es
mindestens 1 Sekunde um diese zu finden. Man muss die ja aber bei
ffclose finden, um den Datei Eintrag zu updaten, das ist das Dilemma.
Bei deinen Werten habe ich raus, 0,01625 Sekunden also 16,25 ms. Ist
jetzt zwar ne Milchmädchen Rechnung, aber das würde Pi mal Daumen so 6-7
Sektoren bedeuten, also ungefähr 112 Dateien durchsuchen....Oder
weniger, wenn vorher noch paar Daten Sektoren geschrieben wurden.
Mach mal ein Verzeichnis mit sagen wir 2000 Dateien (kleinen Dateien)
und ändere dann die zuletzt drauf geschriebene ab. Da müsste sich der
Overhead des Suchens deutlicher bemerkbar machen :)
@ geb (Gast)
Äh verkürztes warten? Kannst du dazu etwas mehr sagen, bitte.
Unterstützung für SDHC klingt auch gut. Ich werde mir deinen Code mal
genauer anschauen :)
PS:
Hat nich mal irgendwer Lust eine FAQ auf
http://www.mikrocontroller.net/articles/AVR_FAT32 zu machen, wo man mal
so alle Try-and-Error-zum-Erfolg Sachen zusammen trägt? Schön wären ja
auch alle möglichen mmc.c/mmc.h für unterschiedliche Plattformen. Bei
mir geht nächste Woche das Semester wieder los => wenig Zeit...
Grüße Daniel
Hiho,
@Daniel,
habe nun mal 2000 Dateien im Bereich von 1-10KB auf die SD-Karte
geschrieben, als letztes die Datei, in der ich schreiben möchte. Nun kam
ich auf Werte von 7.645.224 bis 10.433.112 Takten.
Wow, dafür habe ich meinen Kondensator nicht ausgelegt, also darf in
meinem Verzeichnis keine andere Datei vorhanden sein, damit ich unter
880.000 Takten bleibe.
---
Übrigens, wenn das Semester los geht, hat man doch gerade viel Zeit,
erst zum Ende hin wird es immer knapp (zumindest ist/war es bei mir so)
---
Gruß
Arne
Hallo.
Ja die Werte sehen realistisch aus, leider.
Es gibt bei Conrad 1F bis 5 Volt Goldcaps für um die 2 Euro, auch in
kleiner Bauform. Davon ein paar und das zeug läuft Minuten lang noch :)
Wenn du jetzt 2000 Verzeichnisse mit nur einer Datei drin hast, wird das
auch nicht besser (nur als Beispiel), eher schlechter. Große
Betriebssysteme indizieren deshalb Dateien, um nur Indizes vergleichen
zu müssen, wie bei Datenbanken...
Man könnte vielleicht auch das suchen etwas beschleunigen indem man z.B.
nur den ersten Buchstaben der Datei überprüft und erst wenn der stimmt
weitere Buchstaben. Da mach ich mir mal Gedanken dazu...
Zeit hab ich leider nie genug und dieses Semester wird noch schlimmer...
Grüße Daniel
Noch ein spassiges Problem ist mir in Verbindung von meinem mmc.c
aufgefallen:
Nach dem Schreiben des letzten sektors (file_Update) warte ich nicht bis
die Karte nicht mehr busy ist.(Der Wert 0xE5 als "Daten akzeptiert" ist
das Letzte was ich von der Karte lese.)
dieser letzte Sektor wird bei manchen Karten z.B. Kingston nicht mehr
ins Flash geschrieben. Damit wird das fclose unwirksam und die letzten
geschriebenen Daten (seit letztem öffnen der Datei) gehen verloren.
Offenbar brauchen diese Karten in der busy-Phase den Clock um die Daten
aufs Flash zu speichern. Sandisk-Ultra Karten haben dieses Problem
interessanterweise nicht.
Abhilfe: letzten sektor bei file-update 2x schreiben, oder hier extra
busy Phase abwarten.
Grüße Gebhard
Hallo Daniel,
ich hab ein kleines Problem beim Schreiben von Daten auf SD-Karte.
Ich möchte eine Datei erstellen, Daten rein schreiben, Datei schließen.
In gewissen zeitlichen Abständen möchte ich diese Datei wieder öffnen,
weitere Daten anhängen und Datei wieder schließen.
Beim Erstellen der Datei und beim Speichern des ersten Datensatzes
klappt auch alles wunderbar. Will ich Datei jedoch zum Anhängen von
weiteren Daten mit
ffstatus = ffopen(file_name);
erneut öffnen, liefert ffopen als Rückgabewert 2 (datei muss angelegt
werden) obwohl sie bereits existiert. Die Daten werden dann auch nicht
in die Datei geschrieben. Es sind nur die Daten des ersten
Schreibzugriffs vorhanden.
Ich benutze die AVR-Studio Version 0.5.5
Gruß Kai
Hallo.
@ geb (Gast)
Man muss doch eh pollen ob die Karte busy ist oder nicht. Damit sendet
man doch schon takte...
Orientier Dich da doch an der orginal mmc.c.
Meinst du mit file-update die Funktion flushFileData() ? Wenn ja, die
ist nur für den internen Gebrauch in der file.c. Der User sollte die
nicht benutzen, na ja vielleicht zu Test Zwecken...
@ Kai J. (tairon)
Das klingt seltsam. Wie sieht der String auf file_name aus?
Zeig doch mal den Code mit dem du zuerst die Datei beschreibst. Hast du
irgendwo etwas am Code geändert?
Grüße Daniel
Das hab ich gemacht. Ich bekomm aber vorher schon bei
ffstatus = ffopen(file_name);
eine 2 als Rückgabewert und nicht eine 1.
Ich schätze aber es liegt an meiner UART Routine. Ich benutze die
Library von Peter Fleury.
Moin,
habe mir einen Code geschrieben, um zu sehen wie lang ein ffseek()
(5.5.1) braucht.
Die Datei "1M.TXT" ist 10240 bytes groß, auf einer 1GB FAT32 Karte.
1
while(second<60){
2
uputc(ffopen("1M TXT"));
3
uputs("S");
4
ffseek(file.length);
5
uputs("D");
6
ffclose();
7
}
Beim ffseek knallts. Ich sehe das "rS", das "D" aber nicht mehr. Bei
einer Dateigröße von 1024 bytes funktioniert der Code tadellos.
Irgendjemand eine Idee?
Hallo,
@ Kai J. (tairon)
Kann ich irgendwie nicht nachvollziehen wieso die Uart lib daran schuld
sein soll. Du hast aber mindestens auch noch "#define SMALL_FILE_SYSTEM"
geändert, sonst geht nämlich ffwrites nicht.
@ Gast (Gast)
Ok, teste ich mal. Mit wie vielen Sektoren/Cluster ist denn das
Formatiert, damit ich gleiche Voraussetzungen habe ?
Grüße Daniel
einschränken können.
Ablauf:
file.c (ca. Zeile 163): fat_getFatChainClustersInRow(fat_getNextCluster(
file.lastCluster )) ;
fat_getNextCluster( file.lastCluster ) klappt soweit, geht dann in
fat_getFatChainClustersInRow() und hängt sich da irgendwo auf.
@Daniel
Das ist eben der springende Punkt,in meiner mmc.c polle ich nach einem
sektor-write nicht auf busy,sondern bereite schon die nächsten daten zum
Schreiben vor. Auf "busy" wird dann beim nächsten write-command
gepollt,in der Hoffnung dass das blöde Ding in der Zwischenzeit die
Daten schon mal geflasht hat. ==>funktioniert bei Sandisk tadellos und
erhöht die Schreibrate um 40%,bei Kingston bringts nichts(ohne CLK
offenbar kein flashen).Schon sehr interessant, wie unterschiedlich die
SD Karten sind.
Grüße Gebhard
Hm, wenn der falsche Sektor geladen wird, geht natürlich nix mehr
(fat_loadSector).
Das ist ja keine Variable, sondern ein void Pointer, der zuerst mal auf
nix zeigt, dann aber auf bytesOfSec=&fat.sector[j] , also auf eine
bestimmte char Adresse im Puffer für einen Sektor.
Von dieser "Start Adresse" wird jetzt je nach FAT Typ auf 2 oder 4 Byte
Größe gecastet.
Mit was Kompilierst du den Code? ich hab da mit dem GCC für linux und
dem AVR-GCC keine Probleme. Kann das irgendwie nicht richtig
reproduzieren, werde da aber mal genauere Tests machen. Bis jetzt kann
ich leider keinen Fehler finden...
@ Gebhard
Ich glaube es ist SD Spezifikation das die Karte "CLK hörig" ist, ist
also ein Geschenk, das es mit Sandisk funktioniert...
Grüße Daniel
@Daniel:
gcc 3.4.6 AVR-CrossPack.
Ich lasse mir vor jedem return in fat_getNextCluster den Wert von
bytesOfSec ausgeben mit:
1
putNum(*(unsignedlongint*)bytesOfSec,'w');
Die Funktion macht nix anderes als den übergebenen Wert (unsigned long
int) als Tausender, Hunderter etc. auszugeben. Das 'w' dient der
Unterscheidung. Die Ausgabe schaut so aus:
w00135
w00136
w00137
w00138
w00139
w�P15
w�P15
Die letzten beiden Werte sind IMHO keine korrekten Werte.
Joa, hab ich.
Auch mit nem image von ner Karte mit 8 Sektoren/Cluster.
Wo hast du den 3.4.6 Compiler her?
So, hab mal folgendes:
1. Mit Linux Kompiliert, Fat-resource als "/dev/mmcblk0" eingebunden und
mit der Lib 5.5.1 getestet. Ohne Probleme.
2. Mit Linux Kompiliert und Fat-resource als Image einer Karte
eingebunden. Mit Lib 5.5.1, ohne Probleme.
Kannst du Vielleicht ein Image der Karte machen und mir schicken, damit
ich mit der gleichen Karte testen kann, aber anderen Kompilern usw.?
Grüße Daniel
Okay, das Problem scheint nur aufzutauchen, wenn ich eine Datei lesen
will, die am PC erstellt wurde. Wenn ich eine entsprechend große Datei
mit der Lib generiere, ist alles ok.
Das ist mal seltsam.
Ist die Datei die du dann mit der Lib erstellt hast, denn auf dem Pc
lesbar usw.?
Was definitiv nicht geht ist eine mit Linux Formatierte Karte, da Linux
aus welchem Grund auch immer das Root-Dir, wenn es nur 1 Cluster groß
ist nicht mit 0xfffffff0 abschließt sondern anders.
Mein Interesse an einem Image der Karte besteht immer noch.
Grüße Daniel
Die Datei ist am PC lesbar, ja. Der einzige Unterschied ist, dass ich
bei einer auf dem Atmega erstellten Datei "0FFFFFFF" als bytesOfSec
sehe, und bei der am Mac erstellten das Ganze zwei mal. D.h. die
Funktion wird unnötigerweise nochmal aufgerufen.
Auf dem Mac macht das die GUI :).
Und die führt den Befehl newfs_msdos mit Optionen aus.
Huhu,
ich habe noch mal eine kleine Frage:
Und zwar möchte ich gerne in einer geöffneten Datei, Werte lesen und
danach wieder ans Ende schreiben, mein Programmablauf sieht wie folgt
aus:
ffopen(datei); -> ffseek(file.length); -> 1 bis x-mal ffwrites(werte);
-> ffseek(file.seek+fat.cntOfBytes - (68*100)); (ist die Stelle der
Datei, von der ich lesen möchte) -> 100-mal ffread() ->
ffseek(file.seek+fat.cntOfBytes);
Mein Problem ist nun, dass er mit dem letzten ffseek nicht an die
richtige Stelle geht, damit ich weiter schreiben kann.
Gibt es nun eine Möglichkeit ohne ffclose() mit gefolgten ffopen(datei),
an die richtige Stelle der Datei zu kommen, damit ich weiter
hineinschreiben kann? Also quasi "Fat aktualisieren / file.length
aktualisieren" ohne neue die Datei zu schließen+öffnen?
Grüße
Arne
ffseek-Problem schrieb:
> So, habe mir das Ganze nochmal genauer angeschaut. Der ffseek() hängt> hier:>> mmc.c, mmc_read_sector(...):>>
1
>while(mmc_read_byte()!=0xFE){};
2
>
> Komischerweise bekommt er nur 0xFE zu lesen.
Sieht nach Compiler bzw. Linker Problem aus.
Versuche einmal ein "make clean" und dann ein "make".
Wenn's danach immer noch nicht geht, versuche eine andere
Toolchain/WinAVR Version.
make clean bringt nichts. Habe mal gcc 4.3.2 genommen. Auch keine
Änderung.
Ein Stack-Overflow kann es nicht sein, da die Funktion, so wie ich das
sehe, vorher mehrfach problemlos betreten und wieder verlassen wird.
@Daniel:
Wie erstelle ich das Image der SD, und wie soll ich es Dir zukommen
lassen?
Hallo zusammen.
Ich habe momentan leider echt viel um die Ohren, komme aber
wahrscheinlich dieses Wochenende trotzdem dazu da nochmal etwas
nachzuforschen.
@ Arne Z. (theich)
Du müsstest "#define OVER_WRITE TRUE" machen und dann zwischen schreiben
und lesen die Dateilänge merken, damit du nach dem lesen ein seek dahin
machen kannst.
Ungefähr so:
ffopen(datei); -> ffseek(file.length); -> 1 bis x-mal ffwrites(werte);
-> unsigned long int tmp=file.seek+fat.cntOfBytes;
->ffseek(file.seek+fat.cntOfBytes - (68*100)); (ist die Stelle der
Datei, von der ich lesen möchte) -> 100-mal ffread() ->
ffseek(tmp);-> weiter schreiben an Dateiende.
Das müsste klappen.
@ ffseek-Problem (Gast)
Ich bräuchte als Image einfach eine Datei, in der alle Sektoren der
Karte stehen, bzw alle Bytes. Ich mache solche Images meistens mit
WinHex. Bei einer 1GB Karte wäre es aber wohl am besten nicht alle
Sektoren in die Datei zu packen, sondern nur die die mit Daten belegt
sind. Also von Sektor 0 bis zu dem letzten Sektor mit Daten...
Wie groß wird diese Datei dann bei dir? Geht die noch per Mail?
Grüße Daniel
@ffseek-problem (Gast)
Image ist soweit Ok. Habe jetzt noch nicht auf realer Hardware getestet,
mach ich aber gleich. Das sieht aber alles soweit Ok aus. Auf Linux mit
dem gcc geht es problemlos, was schonmal bedeutet, das der Code an sich
keinen Fehler verursacht.
Kann dann eigentlich nur am Compiler oder der Hardware liegen.
War die Karte auch schon so formatiert bei diesen Tests
Beitrag "Re: MMC SD library FAT16 FAT32 read write" ?
Bei dem jetzigen Image sind die Cluster [124-148] belegt, mach in Summe
25. Das macht bei 8 Sec/Clust 102400 Bytes. Das kommt alles hin. Die
Cluster sind in der Fat auch richtig verkettet und Terminiert...
Grüße Daniel
@ Daniel:
Ich habe auch noch ein paar Tests gemacht und folgendes festgestellt:
Es ist egal, ob ich die Karte auf einem Mac oder einem Windows Rechner
formatiere. Und es ist egal, ob die Datei als einzige auf der Karte
existiert
oder schon andere Dateien physisch vor der Datei liegen.
Ich weiß jetzt leider nicht mehr, wie die Karte bei den Tests, die Du
meinst, formatiert war. Es sollte aber wegen meiner vorhin beschriebenen
Beobachtung unwichtig sein.
Ich habe inzwischen auch mal eine andere SD-Karte probiert, und das
ganze wegen Stack-Bedenken auf einen Mega32 portiert. Immer mit dem
gleichen Resultat.
Die Hardware möchte ich als Fehlerquelle ausschließen, da Sie nach der
Spec von SanDisk aufgebaut ist. Ich werde als nächstes das Ganze mal mit
WinAVR kompilieren und testen. Kannst Du mir sagen welche Version Du
nutzt?
Negativ. Auch wenn ich es mit WinAVR unter Windows mache gibt es immer
den gleichen Fehler. Habe auch auf von 8MHz auf 4MHz heruntergetaktet.
Kein Unterschied.
Vielleicht hilft Dir das noch weiter.
Im Fehlerfall ist bei FAT32:
- in der Funktion fat_getNextCluster():
i = 0x001FFFFF (2097151 dezimal)
fat.fatSec = 0x00000119 (281 dezimal)
- in der Funktion fat_loadSector(), die ja im Anschluss mit i +
fat.fatSec aufgerufen wird
sec = 0x00200118 (2097432 dezimal)
Bei einer Speicherkarte mit 1 GB hab ich Brutto (1024 1024 1024)
Byte / 512 (Byte / Sektor) = 2097152 Sektoren.
Wenn ich das also richtig sehe, versucht der anschließende
mmc_read_sector() auf einen Sektor (2097432) zuzugreifen, der gar nicht
mehr existiert, da die Speicherkarte nur 2097152 Sektoren hat.
Kann das sein?
Das Problem ist, es gibt verdammt viele Möglichkeiten wie das was schief
gehen kann. file.lastCluster wird in fat_getFatChainClustersInRow()
gesetzt...
Wenn ich jetzt halt deine genaue Anwendung der Lib sehen könnte, hätte
ich das Image und hätte somit alles genau so wie du. Dann wohl auch den
gleichen Fehler.
^^ huch zu langsam ;)
Achso...
AVR Memory Usage
----------------
Device: atmega8
Program: 7218 bytes (88.1% Full)
(.text + .data + .bootloader)
Data: 990 bytes (96.7% Full)
(.data + .bss + .noinit)
Sollte ich mir wegen letzterem Sorgen machen? Immerhin hatte ich das
Problem auch bei einem Mega32, der ja 2K RAM hat.
>Data: 990 bytes (96.7% Full)>(.data + .bss + .noinit)
Ist schon ziemlich eng. Mach doch die Ausgaben kürzer wie z.B
> uputs("main ffclose done\r\n");
zu uputs("mcd\n"); oder so
Okay, ich habe jetzt mal den kompletten Unterbau (mmc, file, fat)
ersetzt durch den aus der 0.5.5.1 Lib. Nur die main() habe ich so
gelassen. Keine Änderung. Ausgabe:
Waiting...
main ffopen
main ffseek
Das war's.
Program: 6182 bytes (75.5% Full)
(.text + .data + .bootloader)
Data: 686 bytes (67.0% Full)
(.data + .bss + .noinit)
Hi Jungs,
verfolge mit Spannung euer Problem.
Vielleicht doch ein Hardwareproblem.
Bricht eventuell die Versorgungsspg zusammen ???
Sollteste mal mit einem DSO überprüfen.
Noch viel Spaß
Gruß
Siegmar
Da bin ich platt. Wohnst du zufällig in der Nähe von Köln?
Die Datei ist auf jeden Fall auch vorhanden?
Lass dir mal die Rückgabewerte der Funktionen ffopen(), ffseek() und
ffclose() anzeigen.
>../mmc/fat.c: In function `fat_loadRowOfSector':>../mmc/fat.c:104: warning: left shift count >= width of type
Ja ist aber nur ein Warning und nicht so wild. Das muss so.
Was der " siegmar (Gast) " da schreibt is mir auch schonmal durch den
Kopf gegangen. Wie ist die Stromversorgung bei der Schaltung?
Du solltest messen, ob die Spg. zusammenbricht.
Diese Möglichkeit muß Du sicher ausschließen und schaue Dir auch die
Flanken der Signale an, ob sie nicht zu rund sind.
Hardwarefehler mußt Du meßtechnisch ausschließen !!
So nun gut Nacht
Gruß
Siegmar
@ Siegmar
Jo, Oszi hab ich nicht. Multimeter grad mal :).
Folgendes passiert:
Waiting...
main ffopen
rmain ffseek
main ffclose
1main ffclose done
main ffopen
Dazu muss ich ein wenig ausholen. Das Ganze funktioniert mit 3V3 wie
folgt.
5V (USB) Vcc -> 3V3 über LDO Regler.
5V (USBasp) Signale <-> 3V3 Signale über Levelshifter.
µC <-> SD über 3V3.
3V3 5V
µC ---- Levelshifter ---- USBasp
SD -+
Zunächst ist der Levelshifter (LS) auf HiZ, damit der USBasp die SPI
nicht beeinflusst. Damit erfolgen die ersten 3 Zeilen der Ausgabe.
Sobald ich den LS aktiviere, erfolgt die Ausgabe der Zeilen 4 bis 6.
ABER gleichzeitig wird der RESET des µC auf GND gezogen (hardwired mit
LS). D.h. eigentlich würde er weitermachen, aber es kommt der Reset
dazwischen.
Werd mal den LS loswerden und die vielen Käbelchen die hier
herumschwirren.
Ein Königreich für ein Oszi.
Scheint also kein Softwareproblem zu sein.
Dennoch fetten Dank an Dich Daniel für die Mühe und Hilfe! Und natürlich
für die Lib!
Joa, kein Problem. Ich habe ja auch Interesse daran, da Fehler zu finden
und an der Qualität zu arbeiten :)
Falls du da weiter kommst, lass von dir hören.
Wenn mir noch was einfällt, meld ich mich auch.
Grüße Daniel
Hallo,
normales Oszi würde Dir da auch nicht so sehr helfen, außer die Flanken
betrachten.Mit einem DSO wäre es kein Problem den Fehler einzugrenzen
bzw. auszuschließen.
Einfach mal einen Referenzaufbau verwenden, der bei Anderen 100%
funktioniert. Daniels Aufbau z.B einfach nachbauen , damit ihr
identische Testbedingungen habt. Die Länge der leitungen zur Karte sind
nicht unkritisch und sollten so kurz wie möglich sein.
Wird schon klappen, bleib dran !
Bin gespannt was es war, laß es uns wissen.
Schönen Sonntsag noch
Gruß
Siegmar
auch bei offset==512 noch einmal durchlaufen, macht der aber nicht, das
Programm stoppt einfach !
Wenn man das "while( offset>512 )" so macht, läuft es durch.
Da muss man mal weiter nachforschen !
Schlimmstenfalls sollte offset mit der >= Bedingung ja 0 werden, was
auch richtig wäre.
So der Bug is weg. Schwere Geburt^^
Der Fehler lag in einer Abfrage in ffseek. Warst da schon auf dem
richtigen Weg.
Es konnte unter Umständen dazu kommen, das da verschiedene Grenzen
aufeinander fallen und dieser Fall nicht abgefragt war.
In der Schleife in ffseek muss bei dem if die Bedingung erweitert
werden...
Es gibt da jetzt auch noch weitere Updates in der Lib.
Zu diesem Thema: Beitrag "Re: MMC SD library FAT16 FAT32 read write"
Was der Arne Z. da machen sollte, kann jetzt wegfallen, solange "#define
MMC_OVER_WRITE TRUE" ist.
Es kann jetzt einfach in der main_simple.c eine eigene uart lib includet
werden, da die funktion ffls() jetzt einen Parameter erwartet. Der
Parameter muss ein Funktionspointer auf eine Funktion sein der Form:
void funktionsName(unsigned char*); zum anzeigen der Daten.
Als Beispiel mit der mitgelieferten uart.c: ffls(uputs); und schon
funktioniert das :)
@ ffseek-Problem (Gast)
Danke für deine Ausdauer und Hilfe.
Ich war nur am Zweifeln, weil ich den Fehler nicht reproduzieren
konnte...
Grüße Daniel
Einwandfrei! Vielen Dank!
PS: Habe die file.h leicht ergänzt:
1
#ifndef _FILE_H
2
3
#define _FILE_H
4
#include"config.h"
Sonst hat er gemeckert:
In file included from ../main.c:8:
../mmc/file.h:22: warning: parameter names (without types) in function
declaration
../mmc/file.h:26: error: syntax error before "unsigned"
Ja doch ein Software Fehler.
Das Problem war, bei mir war der nicht aufgetaucht, da fängt man halt an
wo anders den Fehler zu suchen...
Ich glaube es hatte etwas damit zu tun wie ich besagte 1M.TXT, aus dem
Image gelesen hatte.
Na ja, hat ja dann doch noch geklappt^^
Grüße Daniel
Hallo Johannes,
wie ich lese, beschäftigst Du dich ebenfalls mit dem Thema Soft-SPI und
hast schon eine "Vorab"-Variante am laufen. Daniel möchte das in einer
folgenden Version ja auch generell implementieren.
Ich betreibe hier einen Pollin-AVR mit einer für meine Bedürfnisse
modifizierten Software von ROBUE. Robue hat auf der RADIG-Basis eine
AVR-Steuerung entwickelt. Das funktioniert hier alles prächtig.
Nun möchte ich div. Daten in Tages-Files wegschreiben (Datenlogger).
Hierfür suche ich ein integrierbares "Mini-Dos". Hier scheint gerade
sowas zu "entstehen".
Das MMC/SD Slot (nach RADIG) hängt bei meinem AVR an Port D und
funktioniert mit Radigs Testprogramm im Soft-SPI-Mode (mit invertiertem
Clock-Takt). Nun fehlt nur noch die komplette DOS-Variante als
Soft-SPI-Version. Leider bin ich beileibe kein C-Profi und nicht in der
Lage sowas zu schreiben! Kleine Anpassungen hingegen klappen schon.
Kannst Du mir dein "lauffähiges Projekt" zu Testzwecken zukommen lassen
(d.h. deine xxx.c und xxx.h Dateien im Bundle). Ich könnte dies mal auf
meinem AVR laufen lassen und ggf. einige Schnipsel komplett übernehmen.
Ich arbeite hier mit WIN-AVR.
Herzlicher Gruß aus Franken
Bernhard
Hallo Bernhard.
Was meinst du mit:
>...integrierbares "Mini-Dos". Hier scheint gerade>sowas zu "entstehen".
Meinst du eine Lib die Dateien so auf mmc/sd Karten schreiben kann, dass
die auch am PC gelesen werden können?
Soft SPI sollte kein großes Ding werden. Komme ich sogar dieses
Wochenende dazu, glaube ich zumindest mal.
Grüße Daniel
Hallo Daniel, hallo Bernhard!
Ich hatte für meine Zwecke einfach den Soft-SPI-Code aus der von Ulrich
Radig genommenen mmc.c wieder reinkopiert (den du, Daniel, im Laufe des
Projekts offensichtlich entfernt hattest). Das ging aber nicht (siehe
irgendwo weiter oben) und ich habe einige Delays einfügen müssen -
immer bei den clock-Flanken. Ich hatte dafür einfach _delay_us(1);
genommen, weil es das kleinste Zeitintervall war, was mir einfiel. Diese
Inline-Assembler-delays bekam ich damals auf die Schnelle nicht hin.
Siehe hier: Beitrag "Re: MMC SD library FAT16 FAT32 read write"
Bei deinem Code - ich habe ihn fix im MS-NotePad überflogen - sehe ich
gar keine Delays drin. Wenn es so klappt, dann würde mich interessieren,
wie sicher das läuft. Bei mir ging damals mit ähnlichem (sogar fast
gleichem) Code gar nix.
@Bernhard: Ich kann dir gerne mal das Projekt (bzw. die für dieses Thema
relevanten Dateien - sonst wirds ganz schön viel... ^^) zukommen lassen.
Ich bin nur leider gerade am falschen PC und komme an die Dateien nicht
so schnell ran. Lass mir einfach mal deine Mail-Adresse zukommen.
Grüße,
Johannes Neumann
Daniel, ich schon wieder :-)
Die neuen Config-Optionen wie auch die Idee, den UART als Argument zu
übergeben, ist klasse. Damit ist die Lib schön portabel. Wunderbar &
Danke!
Was mich allerdings wundert ist, wie du den UART-Funktionspointer
definierst und verwendest. Das macht so nicht unbedingt Sinn... Also -
irgendwie definiert wird der Funktor (Funktionspointer) in der Config.h.
Hier:
Warum brauch ich hier den MMC_PRINT_DISPLAY define, wenn danach doch
uputs_ptr direkt aufgerufen wird. Was passiert, wenn ich in der config.h
das entsprechende define ändere?
Andere Ansatz
Warum nicht einfach so etwas:
1
lsRowsOfClust(void(*charHandler)(unsignedcharc)){
2
...
3
(*charHandler)(someChar);
4
...
Die Methode definiert die Signatur des Funktionspointers eindeutig.
Dieser wird in der Methode direkt verwendet. Das #define in config.h ist
unnötig. Und so du willst, so kann dort vielleicht auch noch ein typdef
helfen.
Hallo Johannes,
der Code von Ulrich lief so out of the box nicht bei mir.
Ich dachte es liegt daran, das SCK nicht idle Low ist...aber wo ich so
drüber nachdenke könnte es auch andere Gründe haben.
Für die maximal 8-10 Mhz Soft-SPI Takt der AVR sollte man eigentlich
keine Pause in der Kommunikation brauchen. Da sind die Karten schon
schneller.
Läuft denn http://www.mikrocontroller.net/attachment/60728/soft_spi.zip
das bei dir ohne Probleme? Bei mir mit 5 Verschiedenen Karten schon.
Unterschiedliche Frequenzen hab ich noch nicht ausprobiert, halt nur die
16/20 Mhz...
Daniel, dann bitte auch daran denken, die uputs_ptr calls durch das
übergebene Argument der Methode zu ersetzen :-)
Nur als Hinweis, du machst das schon...
cu, Michael
Hallo mal wieder.
Ich habe eben versucht, die Version 0.5.6 zum Laufen zu bekommen. Dabei
brauche ich aber leider noch einige Hilfestellungen...
Zuersteinmal musste ich bei fast allen ffxxx Funktionen die Argumente
ändern. Denn: Seit der letzten Version, die ich hier genommen hatte,
wurden alle string-Argumente von signed zu unsigned char geändert. Bissl
ärgerlich finde ich, denn jetzt kann man nicht mehr
1
ffcd("ORDNER ");
schreiben, sondern muss das so machen:
1
ffcd((unsignedchar*)"ORDNER ");
Vielleicht kann mir nochmal jemand kurz erklären, wieso das so sein
muss.
Desweiteren bekomme ich massenhaft warnings, die ich nicht einfach so
ignorieren möchte:
1
...
2
In file included from main.c:39:
3
./sd/fat.c: In function 'fat_loadRowOfSector':
4
./sd/fat.c:105: warning: left shift count >= width of type
5
./sd/fat.c: In function 'fat_loadFileDataFromDir':
6
./sd/fat.c:157: warning: comparison is always false due to limited range of data type
7
./sd/fat.c:168: warning: comparison is always false due to limited range of data type
8
./sd/fat.c: In function 'fat_cd':
9
./sd/fat.c:192: warning: comparison is always false due to limited range of data type
10
./sd/fat.c: In function 'fat_loadFatData':
11
./sd/fat.c:527: warning: comparison is always false due to limited range of data type
12
In file included from main.c:40:
13
./sd/file.c: In function 'ffopen':
14
./sd/file.c:29: warning: comparison is always false due to limited range of data type
15
./sd/file.c: In function 'ffmkdir':
16
./sd/file.c:284: warning: comparison is always false due to limited range of data type
17
main.o: In function `flushFileData':
18
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:110: undefined reference to `fat_writeSector'
19
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:113: undefined reference to `fat_setClusterChain'
20
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:115: undefined reference to `fat_makeRowDataEntry'
21
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:118: undefined reference to `fat_writeSector'
22
main.o: In function `ffmkdir':
23
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:288: undefined reference to `fat_getFreeClustersInRow'
24
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:289: undefined reference to `fat_setCluster'
25
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:291: undefined reference to `fat_makeFileEntry'
26
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:301: undefined reference to `fat_writeSector'
27
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:305: undefined reference to `fat_makeRowDataEntry'
28
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:306: undefined reference to `fat_makeRowDataEntry'
29
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:307: undefined reference to `fat_writeSector'
30
Kompilierung fehlgeschlagen.
Diese Vergleichswarnungen kann man so einfach nicht übergehen - immer,
wenn ich so einen hatte, gab es arge Probleme. Was tun? Ist ein FASLE
bzw. TRUE bei meinem avr-gcc was anderes als bei euch? Irgendwelche
Vorzeichenprobleme oder so?
Zudem dieses komische Problem in der ffmkdir und flushFileData: Vor und
hinter diesen Funktionen werden diese angeblichen "undefined references"
aber nicht gemeldet: Warum also findet avr-gcc diese funktionen genau
dort und nur innerhalb dieser Funktonen nicht und wie behebe ich das?
Ich bin ziemlich ratlos...
Danke für Hilfe,
StrangeMan
[EDIT] Oh... ich seh gerade: Mache ich den Schalter für die
Schreibunterstützung an, so verschwinden diese komischen
reference-Fehler...
Ok, nachdem ich alle TRUEs und FALSEs durch mTRUE und mFALSE ersetzt
hatte, gings. Wahrscheinlich hatte irgendeine der Libs, die ich sonst
noch verwende, auch TRUE und FALSE definiert. Nur eben eines der beiden
mit negativem Vorzeichen. Vielleicht sollte innerhalb der mmc-lib ein
eigenes TRUE/FALSE genutzt werden, oder zumindest eine Warnung gemacht
werden, wenn die Werte schon vorher (z.B. von einer anderen lib)
definiert sind.
Nein, ganz ohne delays gehts bei mir nicht. Ich hatte ja oben meinen
Code gepostet. Durch Testen bekam ich heraus, dass man jeweils das
untere der zwei von mir eingefügten Delays in beiden Funktionen
(read/write) entfernen kann. Eins muss aber rein.
Achso: Deine Soft-SPI Routinen gehen bei mir nicht. Kann am
invertiert/nicht-invertiert Problem liegen oder an den (bei mir)
mangelnden Delays. Müsste ich nochmal prüfen (mach ich später).
Könnte man vielleicht einfach in der nächsten Version noch einen
Schalter für das Invertieren einfügen?
Grüße,
StrangeMan
./sd/fat.c:105: warning: left shift count >= width of type
sollte das einzige sein was kommen sollte. Und das ist Ok.
Zu dem TRUE und FALSE, vielleicht mach ich da einfach das "#ifndef" weg,
dann sollte zumindest mal die Compiler Warnung wegen doppeltem
definieren kommen.
Ich muss mal sehen ob ich nicht die Tage mal der SPI Geschichte auf den
Grund gehe. Man müsste das ganze mal mit nem Logic-Analizer zerpflücken,
hab ich aber keinen...
Grüße Daniel
Hallo Daniel, hallo Johannes,
Vielen Dank für Euere Antworten. Soeben habe ich Zeit gefunden um wieder
mal am "Projekt" zu primeln. Habe die SOFT-SPI-Dateien ausgetauscht und
die Pins meines ATMega in der Config angepaßt.
--> FUNKTIONIERTE AUF ANHIEB mit 3 verschiedene Karten (512MB bis 2GB
SanDisk, Transcend, Kodak) sowohl FAT16 als auch FAT32, Super-Arbeit
Daniel!!
Eine Frage hätte ich noch. Ich mußte im File main_simple.c die Zeile:
ffls(uputs);
auskommentieren sonst meckert der Compiler mich wie folgt an:
E:\05_06 mit Soft_spi\default/../main_simple.c:80: undefined reference
to `ffls'
make: *** [MMC-Win.elf] Error 1
Build failed with 1 errors and 1 warnings...
Vermutlich habe ich da nochwas nicht ganz verstanden (eilt aber nicht).
Für Johannes,
vielen dank für das Angebot Johannes, hat sich nun aber erledigt da
Daniel so schnell gearbeitet hat.
Herzlicher Gruß aus Franken
und nochmals MERCI !!
Bernhard
Hallo zusammen!
Bei mir läuft die Library leider noch nicht so reibungslos. Ich habe
auch die SPI erweiterung hinzugefügt. Hat allerdings keine Abhilfe
gebracht Ab und zu erstellt mir der Atmega leider noch kryptische Files
obwohl das eigentlich nicht so sein sollte. Ich benutze dazu folgenden
Quelltext :
unsigned char file_name[11]="LOG TXT";
unsigned char new_log[18]="** New logging **";
...
if(sdiswriteable()&&sd_merker==0)//Überprüfungob Karte steckt
durchSchalter
{
while (mmc_init() == FALSE){
nop();
break;
}
if(TRUE==fat_loadFatData()){
sd_merker = 1;
ffopen(file_name);
ffseek(file.length);
ffwrite(0x0D);
sd_laufer=0;
do{
ffwrite(new_log[sd_laufer]);
sd_laufer++;
}while(sd_laufer<17);0,
ffwrite(0x0D);
}
}
if(!sdiswriteable() && sd_merker==1)// SD-Karte auswerfen
{
ffclose();
sd_merker = 0;
}
if(sd_merker==1)
{
portauslesenLAN(daten);
ffwrites(daten);
}
Eigentlich sollte der hier doch nur die Datei Log.txt anlegen und dort
Daten reinschreiben. Mittels sdiswriteable() wird abgefragt ob ein
Schalter umgelegt ist, damit Daten auf der SD Karte gesichert werden.
Ich benutze auch einen ungeraden Quarz (14745600 Hz) könnte das auch
daran liegen? Weiterhin benutze ich einen ATmega644.
Bin für jede Hilfe dankbar
Gruß
Alex
Hallo Alex!
Thema kryptische Files: Ich hatte eine Zeit lang eine 16MB-Karte
(letztendlich waren es 12MB), die mit einer neuen Kamera geliefert
wurde. Die hatte ein FAT12 Dateisystem (da zu klein für FAT16; das
braucht 16MB+). Sobald ich die Schreibunterstützung aktiviert habe,
kamen bei mir auch desöfteren kryptische Files raus, da der Code eben
für FAT16/32 ist und bei FAT12 offensichtlich die FAT kaputtschreibt.
Dann werden teils Daten von der Karte gelesen, die mit der
entsprechenden Datei eigentlich nichts zu tun haben: Das sind dann die
kryptischen Daten.
Also Achtung mit so kleinen Karten!
Ich hoffe, das kann dir weiterhelfen,
Johannes
Hallo,
bin mir nicht sicher, ob es einzig und alleine daran liegt, aber das
>unsigned char file_name[11]="LOG TXT";
muss mindestens 12 Zeichen lang sein. Also:
1
unsignedcharfile_name[12]="LOG TXT";
Wegen dem \0 was bei einem String noch hinten dran kommt.
Sonst sieht das auf den ersten Blick ja Ok aus was du da gepostet hast.
Besteht der Fehler immer noch, musst du ein wenig mehr über die Daten
schreiben, und ob du noch andere Sachen verändert hast.
Wieviel Ram hat dein Controller?
Am Takt des Controllers wird es glaube ich nicht liegen...
Grüße Daniel
Danke schonmal für die Hilfe.
Ich benutze allerdings ein 2 Gig Karte mit Fat32. Daran sollte es
eigentlich nicht liegen.
Das mit den 12 Zeichen anstelle von 11 habe ich auch geändert. Trotzdem
treten immer noch die gleichen Kryptischen Dateien auf.
Anstelle die Datei zu öffnen erstellt der Mikrocontroller dann eine
Kryptische Datei und schreibt da hinein. (Jedenfalls wird die log.txt
Datei manchmal nicht angefasst.) Manchmal tretten auch noch andere
Fehler auf. Z.B. kann die Datei selber nicht vom Computer gelesen
werden. Könnte ja auch mit den Kryptischen Dateien zusammenhängen wenn
irgendwo was auf der Karte wild geschrieben wird.
Eigenlich habe ich die Library nicht verändert. Die Daten die ich auf
die Karte schreibe sind die Portdaten überführt in Strings (als Basis
für das ganze benutze ich das AVR Webmodul vom Ulrich Radig
(http://www.ulrichradig.de/home/index.php/avr/avr-webmodule).
Gibt es den eine Maximale Stringlänge die ich an ffwrites übergeben darf
? Immoment überprüfe ich ob hier der Fehler liegt. Werde euch auf dem
laufenden halten. Wenn euch noch was einfällt wäre ich sehr verbunden :)
Grüße Alex
Hallo zusammen!
Also ich habe den Fehler gefunden (die SD Karte war komplett mit windows
formatiert; )
Aber der Fehler lag darin, dass die Funktion
void ffwrites( unsigned char *s ){
while (*s) ffwrite(*s++);
fat.bufferDirty=1;
}
irgendwie die falsche länge des Strings ermittelt hat, den ich übergeben
habe. Ich habe das abgeändert, indedm ich nun eine Feste Anzahl von
Zeichen mittels ffwrite auf die SD Karte schreibe und es läuft.
Vielen Dank für eure Hilfe !
Nocheinmal Hallo :)
schon wieder der Alex :). Ich habe noch ein Problem. Ich schreibe Daten
auf eine SD Karte. Hiernach lösche ich die Daten oder Formatiere die
Daten mittels XP (der Löscht die Daten ja nicht richtig sondern nur die
Fat-Entry (auch Formatieren hilft nicht wirklich)).
Nun will ich wieder auf die Datei schreiben. Aber anstelle neue Daten in
eine Datei zu schreiben hängt der die Daten einfach an die alten Datei
an (die durch das Löschen ja eigentlich schon gelöscht sein sollten).
Ein generelles schreibe über alle Dateien ist allerdings auch
unerwünscht. Gibt es eine Möglichkeit zu erkennen, ob die Datei von
Windows gelöscht wurde und so das einfache schreiben in gelöschte
Dateien zu verhindern?
Grüße Alex
Hallo,
also du Formatierst mit Windows die Karte, machst Datenträger sicher
entfernen und dann erkennt die lib die Datei nicht als gelöscht?
Klingt seltsam!
Du könntest aber z.B. auch einfach mit der lib die Datei löschen, bevor
du sie neu anlegst um so sicher zu gehen, das du sie wirklich neu
anlegst...
Grüße Daniel
Hallo zusammen!
Also ich würde sagen das das dann nicht der Fehler ist. Selbst nachdem
ich die SD-Karte mit dem tool formatiert habe ging es nicht. Ich habe
allerdings immer noch Fehler. Wenn ich dem Fehler näher gekommen bin
schreibe ich nochmal :).
Grüße
Alex
Hallo,
was gibt es neues an der Front, Alex?
Hab mir dieses Beitrag "Re: MMC SD library FAT16 FAT32 read write"
Problem von dir mal durch den Kopf gehen lassen, ich wette es lag daran,
dass du keinen String übergeben hattest sondern irgendwelche Daten.
Der Punkt ist, ffwrites() schreibt solange Daten, bis es auf '\0' alias
0 trifft. Was ja das Ende eines Strings in c beschreibt.
Wenn in den Daten keine 0 bzw. '\0' vorkommt, wird der Ram Inhalt ab der
Adresse es übergebenen Pointers geschrieben, bis irgendwann im Ram eine
0 steht :)
Folge: Kryptische Datei
Poste doch mal deinen kompletten Code, dann schau ich mir das mal an.
Das Format Problem schau ich mir jetzt gleich nochmal genauer an. Bin
mir aber sicher, dass bei Fat32 beim Formatieren außer dem Fat Bereich
auch zumindest das Root-Dir mit gelöscht wird. Ist also nicht möglich da
so einfach noch Reste einer Datei zu finden. Zumindest nicht in der von
dir beschriebenen Weise.
Grüße Daniel
Beim Formatieren mit Fat32 und Windows XP wird der Fat Bereich gelöscht
und natürlich auch der Root-Dir Bereich!
Somit gibt es keine Möglichkeit so einfach an die Daten zu kommen, die
aber schon noch auf der Karte sind.
Nochmal der Alex,
also das Problem besteht weiterhin. Habe ich auch gedacht, dass das mit
den Strings (oder mit der Länge der Strings) zusammenhängt. Allerdings
Benutze ich immoment nur Quellcode der nach folgendem Schema aufgebaut
ist also keine ffwrites(); Funktionen
while (*zwischespeicher_pointer) ffwrite(*zwischespeicher_pointer++);
Die Kryptischen Dateien sind schon weniger geworden allerdings auch noch
nicht ganz weg. Ich Überprüfe gerade noch ein Paar Möglichkeiten. Mein
nächster Ansatz wird sein, das ich die Zeichenlänge der Strings
irgendwie falsch habe. :) Wenn es Funktioniert sag ich bescheit.
Eine Frage habe ich noch. Und zwar geht es schon meistens relativ gut
aber manchmal kommt es vor das Ich Text finde (ich schreibe nur .txt
Dateien) den ich früher auf die Karte geschrieben habe. Kann es sein das
wenn solch ein Text bei anhängen an die Datei gefunden wird, einfach der
Text mit angehängt wird?
Grüße
Alex
Hmm irgendwie komme ich noch nicht weiter. Ich kann ja mal die wichtigen
Quelltextteile angeben und zeigen was nicht geht.
sd_ms ist sind hierbei Millisekunden(diese werden auch normal in die SD
Karte geschrieben.
unsigned char new_log[18]="** New logging **\0";
unsigned char file_name[12]="LOG TXT";
char after_str[7]="After \0";
char ms_str[4]=" ms\0";
...SD initialisieren...
while(1){
ffwrite(0x0D);
ffwrite(0x0D);
char zwischenspeicher[5];
char* zwischespeicher_pointer;
zwischespeicher_pointer = after_str;
while (*zwischespeicher_pointer) ffwrite(*zwischespeicher_pointer++);
itoa(sd_ms, zwischenspeicher,10); // Into to ascii
zwischenspeicher[4]='\0';
zwischespeicher_pointer = zwischenspeicher;
while (*zwischespeicher_pointer)
ffwrite(*zwischespeicher_pointer++);
zwischespeicher_pointer = ms_str; // Text " ms\0";
while (*zwischespeicher_pointer) ffwrite(*zwischespeicher_pointer++);
}
Was in die SD-Karte geschrieben wird sieht folgendermaßen aus
After 1 ms
101
201
...
Allerdings sollte doch folgendermaßen Sachen in die SD Karte geschrieben
werden.
After 1 ms
After 101 ms
After 201 ms
Die Frage die ich habe ist warum er nach dem ersten Durchlauf die
Strings z.B. nicht mehr mitausgibt.
Grüße
Alex
Noch eine Anmerkung wenn ich
zwischespeicher_pointer = after_str;
while (*zwischespeicher_pointer) ffwrite(*zwischespeicher_pointer++);
in
for(uint8_t i=0;i<11;i++)
{
ffwrite(after_str[i]);
}
umwandel schreibt mir der ATmega alle möglichen Strings auf die SD Karte
die eigenlich für Usart verwendet werden. Das verstehe ich auch noch
nicht.
Gruß Alex
OK Problem gelöst.
Falls ich die Strings folgendermaßen auf die SD-Karte schreibe
ffwrite('A');ffwrite('f');ffwrite('t');ffwrite('e');ffwrite('r');ffwrite
(' ');
geht es ohne Probleme. Ich weiß allerdings nicht wirklich warum :).
Danke für Eure Hilfe!
Gruß
Alex
Hallo Alex!
Ich hab mich jetzt nur kurz mit deinem Problem beschäftigt, aber etwas
ist mir aufgefallen:
while (*zwischespeicher_pointer) ffwrite(*zwischespeicher_pointer++);
Da ist doch genau das selbe Problem wie in der ffwrites: Das Ding hört
nur auf, wenn am Ziel des Pointers Null steht (Bedingung der Schleife).
Du sagtest jedoch, dass es an diesem \0-Problem nicht liegen kann, weil
du die ffwrites-Funktion nicht verwendest. Dein Code macht aber genau
das selbe wie diese Funktion.
for(uint8_t i=0;i<11;i++)
{
ffwrite(after_str[i]);
}
Da passiert folgendes: Du greifst auf das i-te Byte nach dem Pointer
"after_string" zu. Da dieser aber nur 7 Byte groß ist, und du hier 11
Bytes liest, liest der uC über das Ende von after_string hinaus. Daher
kommt der Müll von den USART-Routinen, der eben zufällig im Speicher
dahinter liegt.
Keine Ahnung, ob das jetzt so 100% richtig ist, ich habe selbst erst vor
zwei Jahren angefangen mit C. Aber vielleicht hilfts ja doch. =c)
Johannes Neumann
Hallo Johannes
aber wie kommt es dann das auch bei
for(uint8_t i=0;i<11;i++)
{
ffwrite(after_str[i]);
}
Müll rauskommt?
Ich meine der ließt ein Paar bytes rüber aber bei mir auf der SD-Karte
stehen nachher sehr viele Strings die mehr als 3 oder 4 Byte drüber
gehen. Das hat mich so sehr gewundert.
Hallo,
hab heute und morgen nicht viel Zeit...
Lass dir doch mal immer wenn du etwas schreibst, das auch anzeigen, z.B.
über uart, vielleicht grenzt das etwas ein.
>Ich meine der ließt ein Paar bytes rüber aber bei mir auf der SD-Karte>stehen nachher sehr viele Strings die mehr als 3 oder 4 Byte drüber>gehen. Das hat mich so sehr gewundert.
Bist du sicher, dass nicht vielleicht auch alte strings von vorherigen
Versuchen dort stehen?
Grüße Daniel