Hallo,
ich hab ein kleines Problem. Es geht ums lesen einer beschriebenen SD
Karte. Einmal mit Windows formatiert und einmal mit Linux. Die SD Karte
wurde beide male mit FAT16 formatiert und es wurde eine Datei darauf
erstellt, in die etwas geschrieben wird.
Mit Win_Formatierung folgendes Problem:
Nach dem beschreiben mit dem Atmega32 meldet der Controller, dass es
richtig beschrieben und richtig ausgelesen wurde aber
Windows(verschiedene Editoren) und Linux lesen die beschriebene Datei
nicht richtig aus. Alle Editoren stoppen nach 18 Zeichen. Linux sagt,
das ein EOF fehlt und Windows sagt natürlich nichts.
Mit Linux_Formatierung:
Der Controller meldet richtig beschrieben und richtig ausgelesen aber
die Editoren in Windows und Linux zeigen beide eine leere Datei an. Bei
Linux sieht man, dass nicht in die erstellte Datei geschrieben wurde
sondern irgendwo sonst auf der SD Karte. Es wurden also neue
"Verzeichnisse" angelegt, mit den Daten als Namen, die in Windows aber
nicht zu sehenh sind.
Ich benutze den SourceCode von Ullrich Radig.
Kennt einer dieses Problem?
Was kann man da gegen tun?
Gruß,
Marian
>Es wurden also neue>"Verzeichnisse" angelegt, mit den Daten als Namen, die in Windows aber>nicht zu sehenh sind.
Die Daten wurden an die falsche Stelle geschrieben.
Klarer Fall von Fehler in der Software.
@Uhu: Was bringt es mir die Karte mit Tiny Hexer anzuschauen? Ich kann
da nichts erkennen.
@Holger: Hier ist mein Programm, vielleicht siehst du ja einen Fehler.
1
//Hauptprogramm
2
intmain(void)
3
{
4
//Initzialisierung der seriellen Schnittstelle
5
IOInit();
6
7
//öffnet einen kanal für printf
8
stdout=&mystdout;
9
10
//Initialisierung der MMC/SD-Karte
11
printf("System OK\n\n");
12
while(mmc_init()!=0)//ist der Rückgabewert ungleich NULL ist ein Fehler aufgetreten
13
{
14
printf("** Keine SD Karte gefunden!! **\n");
15
}
16
printf("Karte gefunden!!\n");
17
fat_cluster_data_store();//laden Cluster OFFSET und Size ins EEPROM
Als ich ein Fat16 Dateisystem entwickelte trat folgender Fehler auf:
laut FAT16 Spec(PCIntern 3.0) darf der letzte Sektor einer Datei in der
FAT
mit dem Wert FFF7..FFFF gekennzeichnet sein. Es war festzustellen daß
bei Verwendung der Werte FFF7..FFFF zumindest bei "Notepad" nur eine
leere Datei angezeigt wurde. Der Doseditor "Edit" hatte dieses Problem
nicht. Testsystem
Win2000 Stand 2003.
Schau dir doch mal mit dem Hexeditor an, wie die Datei in der FAT
abgeschlossen ist.
Editieren ging ja hier nicht oder?
Habe mich nämlich gerade vertan. Ich hatte sie eben nicht mit dem
Controller sondern mit Windows beschrieben und so sieht meine Datei auf
der SD Karte aus, wenn ich sie mit Windows beschrieben habe.
Mein Atmega kann diese Datei auch so richtig auslesen, ich kann halt nur
nichts reinschreiben, was ein Rechner dann auslesen kann.
Gruß,
Marian
>Ist ein Sektor 512 Byte groß? Wenn ich nun 512 Byte in meine>Datei geschrieben habe, muss ich am Ende des ersten Sektors gucken oder?>Im ersten Sektor steht folgendes: ...Hex>Kannst du damit was anfangen?
ja
>Ich nämlich nicht viel
und das ist das Problem
1. ein Sektor ist 512 Byte groß
2. nein
zu dem Hex, was du da geschickt hast ist der Bootsektor des FAT16 zu
erkennen an EB 3c 90 das ist ein jmp zum Bootprogramm und dem
abschließenden 55 AA.
Dekodiere ihn und suche dir die Adresse des Hauptverzeichnisses , suche
dort den Dateieintrag (ich gehe mal davon aus das sie im
Hauptverzeichnis liegt) dort suchst du dir die Clusternummer raus. Diese
Clusternummer suchst du in der 1. FAT und folgst der Clusterkette bis
ans Ende. Überprüfe wie lang die Clusterkette ist und womit sie
abgeschlossen ist.
Einführende Literatur:
PCIntern 3.0 ,Tinschert
Ein paar Fragen, um zu wissen ob ich etwas richtig verstanden habe:
Das Programm was ich von Ullrich Radig habe, sucht doch schon auf der SD
Karte nach der Datei und deren Clusternummer sowie Adresse usw. Genau
das soll ich doch jetzt mit dem Hexeditor machen oder? Aber wozu soll
ich das machen, wenn das eigentlich vom Programm erledigt wird? Die
Clusternummer zeigt mir doch an, wo die Datei startet und mit den Blocks
kann ich dann immer 512 Byte dort hinein schreiben.
Ich meine, das Programm schreibt doch nur etwas in die Datei, wenn diese
auch gefunden wurde. Liege ich falsch, wenn ich denke, dass dann auch in
die gefundene Datei geschrieben wird?
Entschuldigt, falls die fragen verwirrend sind aber das Thema ist recht
neu für mich und ich steige da noch nicht richtig durch.
>Ein paar Fragen, um zu wissen ob ich etwas richtig verstanden habe:
du hast das genau richtig verstanden.
Tatsache ist, irgendetwas läuft schief, deshalb kommt es zu
"Lesefehlern"
bei Win und Linux. Das heißt du mußt überprüfen was schief läuft.
Da die Problematik neu für dich ist, bist du höchstwahrscheinlich nicht
in der Lage Fehler zu erkennen ohne dich in die FAT16 Strukturen
einzulesen.
Ich kenne den Code von Uli Radig nicht. Entweder ist dort ein Fehler
(eher unwahrscheinlich) oder du verwendest ihn falsch. Die meisten FAT16
Implementierungen aus dem Hobbybereich die ich kenne können Dateien
nicht vergrößern oder neu anlegen. Ich weiß nicht ob dies für Uli Radig
Implementierung zutrifft.
Ich habe endlich das Problem verifiziert.
Das Auslesen unter Windows funktioniert nur, wenn man beim Erstellen der
Datei auch etwas hineinschreibt. Lässt man diese leer und versucht sie
mit dem Controller zu beschreiben passiert nichts. Schreibt man
allerdings etwas hinein, kann Windows auch das lesen, was der Controller
zuvor hineingeschrieben hat.
Ich weiß nicht ob das an meiner Unwissenheit lag aber ich finde, dass
man das ruhig hätte erwähnen können :).
Mal schauen wie lange das nächste Problem auf sich warten lässt.
Gruß,
Marian
Als Alternative kann ich den Code von elm-chan empfehlen:
http://elm-chan.org/fsw/ff/00index_e.html
Damit können Dateien und Verzeichnisse gelesen/erstellt/umbenannt/...
werden. Funktioniert bei mir (ATmega644 und diverse microSD-Karten)
einwandfrei.
EDIT: Editieren ist hier übrigens durchaus möglich, aber nur wenn du
angemeldet bist.
Hm hört sich interessant an und sieht auch so aus, nur leider habe ich
gerade nicht die Zeit da auch noch reinzugucken.
Ich komme ja mit dem Code von Uli ziemlich gut klar mittlerweile aber
ein Problem habe ich immer noch bzw. ich weiß nicht warum das so ist.
Ich schrieb ja folgendes:
"Schreibt man
allerdings etwas hinein, kann Windows auch das lesen, was der Controller
zuvor hineingeschrieben hat."
Das stimmt leider nicht ganz. Je nach dem wieviel man mit Windows in die
Datei hineinschreibt, so viel kann auch nur der Controller
hineinschreiben(zumindest so, dass es Windows lesen kann), also wenn man
10 Zeichen in die Datei schreibt, kann Windows auch nur 10 Zeichen aus
der durch den Controller beschriebenen SD Karte lesen. Ich finde das
ziemlich seltsam, kann mir das vielleicht jemand erklären?
Mir fällt gerade noch etwas ein. Kann man mit dem Code von Uli immer nur
512 Byte schreiben, also muss ich mein Array immer mit 0 auffüllen. wenn
es nicht 512 Byte enthält?
PS: Ich hoffe, dass ließt mal jemand der sich mit dem Code von Uli
auskennt :)
Gruß,
Marian
Also ich kenne den Code von Ulrich Radig nicht. Aber mit deinen
Beschreibungen würde ich mal darauf tippen, dass der Code nur den Inhalt
einer existierenden Datei verändert, nicht aber deren "Header", also den
Eintrag im TOC/FAT. Will heissen, die Dateilänge bleibt schlicht und
einfach immer gleich. Und ja, es können immer nur 512 Byte geschrieben
werden, das liegt aber nicht am Code, sondern an der SD-Karte. Je nach
Implementierung fällt das aber nicht auf, da ein Puffer implementiert
ist.
>PS: Ich hoffe, dass ließt mal jemand der sich mit dem Code von Uli>auskennt :)
Also wenn das Uli's SourceCode2_5 ist solltest du wirklich
auf was anderes umsteigen. elm wurde oben ja schon erwähnt.
Habe ich auch schon ausprobiert. Klappt gut. Kann auch FAT32
und SDHC Karten.
Das ist von mir:
http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT
Sehr einfach zu bedienen ! Hält sich einigermaßen an die
Befehlsnamen die man vom PC her kennt. elm kann zwar mehr,
dafür bin ich schneller ;) Liest und schreibt FAT12,16,32.
SDHC geht auch.
Dann gibts in der Codesammlung noch Roland Riegel (nur FAT16 ?).
Hab ich einen vergessen ?
Bei elm und meinem FAT kannst du selber Dateien mit dem
uC erzeugen. Die müssen nicht vorher mit Windows draufgespielt
werden. Und du kannst gnadenlos in die Datei reinschreiben so
viel du möchtest. Bis die Karte voll ist. Das geht bei einem
Byte los, bis zu soviel Speicher wie du entbehren kannst.
Gruß
Holger
> RAM Bedarf ohne FAT-Buffer ca. 0.7kB. Mit FAT-Buffer 1.2kB
Was ist denn bei dir ein FAT-Buffer? Ich hoffe doch, dass die 512
benötigten Bytes zum Schreiben schon in den 0.7kB enthalten sind, oder?
Sonst wäre das ein Argument, deinen Code nicht zu verwenden ;)
@holger: Deine Routinen höhren sich auch gut an :). Ich werde diese
gleich mal testen. Ich habe noch eine Frage zu diesem hier :
//###################################################################
// unsigned char Fopen(char *name, unsigned char flag)
//###################################################################
Funktion: Öffnet eine Datei zum lesen ODER schreiben
Parameter: "name" ist der DOS 8.3 Name der zu öffnenden Datei
"flag" F_READ Datei zum lesen öffnen
"flag" F_WRITE Datei zum schreiben öffnen
Rückgabe: F_OK wenn die Datei geöffnet werden konnte.
F_ERROR wenn die Datei nicht geöffnet werden konnte
oder bereits eine Datei offen ist.
Wenn F_WRITE benutzt wird und die Datei noch nicht
existiert, wird versucht eine neue Datei anzulegen.
Wenn die Datei bereits existiert wird an ihr ENDE
vorgespult um Daten anzuhängen. Es ist nicht vorgesehen
alte Daten zu überschreiben.
Das aktuelle Verzeichnis wird automatisch vergrößert wenn
keine Einträge mehr frei sind. Das geht bei FAT12 und FAT16
nicht wenn man sich im RootVerzeichnis befindet. Die Anzahl
der Einträge ist fest vom Dateisystem vorgegeben.
Wer mehr als 512 Dateien anlegen will MUSS bei FAT12 und
FAT16 in einem Unterverzeichnis arbeiten !
Habe ich es richtig verstanden, dass man unbedingt ein Unterverzeichniss
braucht, um Dateien automatisch vergrößern zu lassen? Also wenn ich im
Rootdirectory eine Datei habe, dann kann ich diese nicht mit deinen
Routinen benutzen,wenn sie größer werden soll?
Gruß,
Marian
> Habe ich es richtig verstanden, dass man unbedingt ein Unterverzeichniss> braucht, um Dateien automatisch vergrößern zu lassen?
Nein!
Es geht hier um die ANZAHL DER MÖGLICHEN EINTRÄGE (Files) im
Rootverzeichnis.
Die ist bei FAT16 theoretisch 512.
In der Praxis aber nur 255, weil unter Windows zusätzlich Platz für die
langen Dateinamen vergeudet wird.
Versuch mal unter Windows mehr als 255 Dateien ins Rootverzeichnis
Deiner Flashkarte zu kopieren :-)
Wenn Du eine Datei überschreiben willst, musst Du den Dateizeiger auf
den Anfang setzen können (geht normalerweise mit "Seek"). Musste gucken,
ob Dein Projekt Seek hat. Bei Roland Riegel gehts.
Eines aber ist klar:
Du wirst Dich wohl oder übel mit der Theorie der FAT-Filesysteme
auseinandersetzen müssen. Es gibt tonnenweise Infos im Web.
Anhand Deiner Fragen ist ersichtlich, dass Du wenig Ahnung hast.
Dein Projekt wird sonst scheitern, sobald irgendeine Kleinigkeit nicht
passt.
Joachim
Ja, ich weiß selbst das ich nicht genug Ahnung habe aber daran kann ich
jetzt so schnell nichts ändern, da dieses Gebiet auch sehr umfangreich
ist.
Ich habe überall im Netz nur gelesen, wie einfach es ist SD Karten mit
µCs zu verwenden. Das Lesen einer ist ja auch recht simple nur das
beschreiben bereitet mir Kopf zerbrechen, da ich momentan nur noch ca.
1KB Ram übrig habe. Da kam mir der Code von Uli recht passend, da er
sehr klein war :). Leider wusste ich vorher nicht, dass das beschreiben
mit diesem Code nicht ganz so einfach ist.
Ich habe nun den von elmchan (http://elm-chan.org/fsw/ff/00index_e.html)
ausprobiert aber der benötigt viel zu viel Speicher.
Jetzt werde ich mich noch an Holgers Code
(http://www.holger-klabunde.de/avr/avrboard.htm#FullFAT) versuchen aber
da weißt ich noch nicht so ganz, was ich alles benötige wenn ich "nur"
schreiben und lesen möchte, da in seinem FATSingle-Ordner doch sehr viel
Dateien sind.
Mal schauen ob ich das geordnet bekomme.
Gruß,
Marian
Ich bins mal wieder :),
ich habe nun den Code von Holger zum laufen gebracht aber es gibt einige
Probleme. Es hapert in der GetDriveInformation() Routine.
Die Routine arbeitet leider nur bis zum Punkt, wo der FAT Typ bestimmt
werden soll, also bis hier :
1
loop=0;
2
do
3
{
4
// Jetzt checke ich doch den FAT-String im Bootsektor um den Typ der FAT
5
// zu bestimmen. Einen besseren Weg sehe ich im Moment nicht.
6
if(boot->eb.rm.BS_FilSysType[0]=='F'
7
&&boot->eb.rm.BS_FilSysType[1]=='A'
8
&&boot->eb.rm.BS_FilSysType[2]=='T'
9
&&boot->eb.rm.BS_FilSysType[3]=='1')
10
//Wenn ich hier ankomme habe ich entweder FAT12 oder FAT16
}while(loop<2&&FATtype==0);//Bis zu zwei Versuche den Bootsektor zu lesen
Vorher kann ich folgendes auslesen : c_size,c_size_mult,DriveSize und
maxsect. Die Werte stimmen leider nicht ganz, z.B. ist Drivesize nur
98816KB groß, obwohl ich eine 128MB Karte verwende. Jedenfalls wird in
der oben genannten Routine keine FAT-Art erkannt und wenn er danach den
bootsector lesen möchte ist ganz schluss, da bootSecOffset den Wert
4294967295 hat und somit bricht er dann natürlich in der
ReadSector-Routine ab. Leider bin ich jetzt bei der Fehlersuche hängen
geblieben. Ich habe versucht, alles einzustellen was geht(also alle
defines usw.) aber es ändert sich nichts an meinem Problem.
Hat jemand eine Idee woran das liegen kann?
Gruß,
Marian
Hm, woran liegt es dann? Keine der beiden if-Abfragen auf den FAT1. oder
FAT32 trifft zu. Ich verstehe das nicht. Mit der falsch ausgelesenen
Kartengröße hat das nichts zu tun?
>Drivesize nur 98816KB groß
Was zeigt Win denn für Speicherplatz an ?
Das der FAT Typ nicht erkannt wird könnte
daran liegen das deine Schaltung 8MHz SPI Tempo
nicht mag. Wie sieht die aus ?
@Rufus: Damit kenne ich mich leider nicht so gut aus...was meinst du
damit?
Den Schaltplan darf ich leider nicht online stellen, deshalb schreibe
ich es euch:
-Atmega32-L mit 7.3728MHz, d.h. SPI Takt von 57,6 KHz
-Versorgung: LiPo-Akku 3.6 V , 1200mAh
Ich verwende keine Spannungsteiler an den SPI Leitungen, da mein ganzes
System durch 3.3V Spanungsregler begrenzt wird, d.h. die Pins der SD
Karte sind direkt mit dem Atmega32 verbunden. Ich habe auch noch einen
Sensor in der Schaltung, den ich Problemlos über SPI auslese.
Na, Du liest ja offensichtlich irgendwelche Daten von der SD-Karte. Und
die interpretierst Du mit Deinem geposteten Code. Statt das zu tun,
könntest Du ja auch alle Bytes, die Du da liest, als Hexdump irgendwohin
ausgeben.
Würdest Du einen Debugger einsetzen, dann könntest Du Dein Programm nach
dem Lesen anhalten und Dir den Speicherinhalt näher ansehen, aber
anscheinend arbeitest Du ohne Debugger.
Mir ist wirklich vollkommen schleierhaft, warum sich das noch jemand
antut. Moderne Microcontroller bieten mit ihrem JTAG-Interface nun
wirklich hervorragend komfortable Möglichkeiten zum Debuggen, die sollte
man dann auch nutzen.
Marian wrote:
> Den Schaltplan darf ich leider nicht online stellen, deshalb schreibe> ich es euch:>> -Atmega32-L mit 7.3728MHz, d.h. SPI Takt von 57,6 KHz> -Versorgung: LiPo-Akku 3.6 V , 1200mAh>> Ich verwende keine Spannungsteiler an den SPI Leitungen, da mein ganzes> System durch 3.3V Spanungsregler begrenzt wird, d.h. die Pins der SD> Karte sind direkt mit dem Atmega32 verbunden. Ich habe auch noch einen> Sensor in der Schaltung, den ich Problemlos über SPI auslese.
Läuft der AVR jetzt auch wirklich an 3.3V oder immer noch direkt am
Akku?
Also das Problem hat sich seit heute Morgen irgendwie von alleine gelöst
bzw. ich weiß nicht warum es jetzt funktioniert.
@Rufus: Das soetwas geht wusste ich auch noch nicht. Ich habe aber das
JTAG Interface eh deaktiviert.
@Philipp: Nein der Atmega läuft nicht mit 3.3 V sondern hängt direkt am
Akku.
Jedenfalls kann ich jetzt die Karte richtig auslesen und auch
beschreiben und lesen.
Auch hier noch einmal ein Dank an alle die mir geholfen haben.
Gruß,
Marian