Datum:
Angehängte Dateien:Hallo zusammen! In den letzten Tagen habe ich mein MMC/SD-Interface für AVR-Controller fertiggestellt. Dem ein oder anderen wird es inzwischen vielleicht schon ein bisschen zuviel, schließlich gibt es dafür schon eine ganze Menge Alternativen, aber ich wollt es eben selber machen. Implementiert habe ich den low-level-MMC-Zugriff, den Zugriff auf die Partitionstabelle und FAT16 Lese- und Schreibunterstützung. Auf http://www.roland-riegel.de/sd-reader/ findet Ihr meine Testschaltung und den ausführlich dokumentierten Quellcode. Ich habe das aber auch an diesen Beitrag angehängt. Testen konnte ich nur mit einer einzigen 128MB-Karte, es könnte also sein, dass es mit anderen Karten noch Probleme gibt. Vielen Dank noch an Ulrich Radig, von dem ich mir die einfache, aber gut funktionierende MMC-Anbindung mittels Spannungsteiler abgeschaut habe. Über Anregungen und Kommentare würde ich mich freuen. Gruß, Roland
Datum:
Igitt was haben denn deine *.c fürne komische formatierung. Schade, nix mit Editor anschaun, törnt mich grad ab das reinzuziehen.
Datum:
@Senf: Sieht bei mir okay aus. Deine Wortwahl und Schreibstil lassen eher vermuten, daß Kiffen doch gesundheitsschädlich ist ;)
Datum:
@Senf Ich habe die Anwendung unter Linux entwickelt, daher haben die Textdateien die Unix-Zeilenende-Markierung. Wenn Du Sie aber mit einem vernünftigen Editor öffnest und nicht grad mit dem Windows-Einfachst-Editor, dann ist alles ok. Sogar Wordpad schafft das.
Datum:
@Roland Da du ja ohne FAT-Buffer etc. arbeitest, interessiert mich die Geschwindigkeit die du erreichst. Hast du schon mal was gemessen?
Datum:
@SuperUser Ich habe jetzt mal mit einer 32kB-Datei gemessen. Der Durchsatz liegt beim Lesen von 8Byte-Blöcken nur bei ca. 400B/s. Das überrascht mich selbst ein bisschen, aber bei genauerer Betrachtung kommt das schon hin. Denn für den ersten Cluster (also bis 16kB) braucht er nur ein bis zwei Sekunden. Der hauptsächliche Grund hierfür dürfte sein: Im Dateideskriptor speichere ich den Cluster der aktuellen Dateiposition nicht mit ab, sondern suche mir diesen immer neu. Solange ich beim Lesen innerhalb des ersten Clusters bleibe, ist er verhältnismäßig schnell, da er jeden 512Byte-Block wirklich nur einmal liest. Nach dem ersten Cluster bricht er dann ein, da der Block-Puffer durch das zwischenzeitliche Suchen des Clusters nicht mehr greift. Ursprünglich hatte ich sogar den Cluster vom vorangehenden Lesevorgang abgespeichert, hatte dann aber Probleme bei Dateien, die genau auf einer Clustergrenze enden. Sonstiges: - Sehr geringe Blockgröße pro Lese-Aufruf. - Wie Du schon gesagt hattest: kein FAT-Puffer. Der wäre aber schon bei meiner 128MB-Karte 15kB groß, man kann sich das also nur mit externem RAM leisten. - SPI läuft mit 250kHz, also brutto max. ca. 30kB/s. Ich denke, ich muss den Cluster doch zwischenspeichern. Das ist mir jetzt klar geworden. Danke :)
Datum:
Angehängte Dateien:Die schlechte Lesegeschwindigkeit durch die fehlende Zwischenspeicherung der Clusternummer habe ich nun korrigiert. Im Anhang findet ihr den neuen Quelltext. Das Auslesen einer 1MB großen Datei dauert nun 52 Sekunden, das entspricht also ca. 20kB/s. Über weitere Beiträge würde ich mich freuen.
Datum:
Sehr interessant :) überlegst du eigentlich auch ein Programm zum schreiben von daten zu entwickeln? Ich hatte mal folgende Idee: Von einer SD Karte daten lesen und diese dann auf einer Festplatte abspeichern...(speziell für Fotos) ich weiss nicht mit wieviel aufwand das zu realisieren ist.
Datum:
@Fabian > überlegst du eigentlich auch ein Programm zum schreiben von daten > zu entwickeln? Was meinst Du damit? FAT16 Schreibunterstützung? Die ist doch schon implementiert?
Datum:
Wie zu Beginn gesagt, das war die Idee von Ulrich Radig. Natürlich ist das recht einfach, aber wenn man eine Schaltung nur für Testzwecke entwirft, brauchts nicht mehr. Ansonsten kann man ja einen 3,3V-Spannungsregler verwenden, der dann oft ohnehin noch von anderen Komponenten benötigt wird.
Datum:
@Roland ja sorry habe mich etwas unsauber ausgedrückt: Schreiben ist zwar möglich aber nur mit einer sehr geringen Geschwindigkeit, oder habe ich da etwas falsch verstanden? Weisst du zufällig wie man diese Geschwindigkeit erhöhen könnte auf z.b. 1MB/s ?
Datum:
Nein, solche Geschwindigkeiten sind wohl nicht möglich. Soweit ich mich erinnere, unterstützen die Karten im verwendeten SPI-Mode nur max. 400kHz, also brutto 50kB/s. Für 1MB/s wären demnach über 8MHz nötig, was sowohl die Karte als auch den AVR weit überfordert.
Datum:
MMC karten unterstützen bis zu 20 Mhz SPI takt. steht auch in den datenblättern.
Datum:
@Lupin, Gast Danke für die Info. Meine Datenblätter sind ziemlich knapp und an einigen Stellen stark gekürzt. Ich habe den SPI-Takt nun auf das Maximum von 8MHz bei 16MHz CPU-Takt gestellt. Statt 52 Sekunden braucht der uC nun nur noch 13 Sekunden, um 1MB auszulesen. Das entspricht 78kB/s. Hmm, doch nicht so viel schneller... @Pete Von Reichelt, CONNECTOR SD 21 oder 22, leider sehr teuer.
Datum:
Ich meine mal auf wikipedia gelesen zu haben das SD oder MMC maximal 2mb/s kann... ich denke mal es liegt aber einfach an der Ansteuerung mit SPI und die meisten karten erreichen den wert nicht wirklich. 78kB/s ist aber doch schon recht langsam, wenn ich mit der Geschwindigkeit am PC zugreifen müsste würde ich irgendwann durch drehen (wenn man nur mal daran denkt eine 4gb karte zu füllen). Ich wusste gar nicht das die reichelt connectoren einen auswurf mechanismus haben...
Datum:
Nun ja, es ist ja ein AVR und kein PC... Es ginge wahrscheinlich um vieles schneller wenn der FAT16-Overhead nicht wäre. Gerade auf den AVRs mit ihren 8Bit-Registern ist das nicht zu vernachlässigen, da FAT16 viele 16Bit- und 32Bit-Operationen benötigt. Ich vermute, das es auf einem MSP430, ARM oder auch AVR32 wesentlich besser liefe. Werde es auch mal mit größeren Blockgrößen versuchen. Im Moment lese ich ja immer nur 8Byte pro read-Aufruf.
Datum:
@Pete Es gibt auch wesentlich billiger Sockets. Ich weiss gerade keinen Shop in DE, der das zu diesem Preis schafft, aber diese hier (CH) können das: http://www.compona.ch (~2CHF) http://www.farnell.ch (2-19CHF, je nach Ausführung) Es kommt einfach darauf an, was für Ansprüche du an den connector hast. Wenn du nicht einen suuuper duuuper Connector mit Schirmung und Schleudersitz brauchst, dann bekommst du einen für weniger als zwei Euronen. Gruss, Matthias
Datum:
Habe jetzt nochmal verschiedene Puffergrößen ausprobiert, die ich
fat16_read_file() übergebe. Das hat, wie sich gezeigt hat,
entscheidenden Einfluss:
Puffer (B) | Zeit (s) | Geschw. (kb/s)
------------------------------------------
8 | 13 | 78
16 | 9 | 114
32 | 6 | 171
64 | 5 | 205
Also eine Steigerung um das 2,5-fache.
Datum:
also mit so kleinen reads ist das auch echt ineffizient... warum liest du nicht 512 byte pro read command? Wie machst du das denn bei der MMC funktion? Führst du partial reads aus? Im Normalfall wirst du immer 512 byte blöcke von der karte lesen müssen, die restlichen bytes "weg zu schmeißen" kostet natürlich viel Zeit. Wenn es tatsächlich um hohe Transferaten geht, dann wird ja meistens auch in großen Blöcken gelesen, logisch oder? :)
Datum:
Na wahrscheindlich geht ihm das RAM aus.... leider immer das selbe, irgendeinmal trifft man auf die Grenze der AVRchen.
Datum:
Richtig. Ich habe nur 1 kB RAM, die Hälfte davon nutze ich als Schreib-/Lesepuffer für die low-level-Lesefunktionen. Den Rest brauche ich für Dateisystem-, Datei- und Verzeichnis-Deskriptoren und natürlich für den Stack. Ich wollte den Kartenzugriff so flexibel wie möglich halten. Die höheren Schichten (also Partitionshandling sowie FAT16) wissen überhaupt nichts davon, dass sie von einer MMC/SD-Karte lesen, geschweige denn dass dies für gewöhnlich in Einheiten von 512 Byte geschieht. Die MMC/SD-Funktionen bieten "nach oben" die Möglichkeit an, Daten beliebiger Länge von einem beliebigen Offset anzufordern oder dorthin zu schreiben, egal ob das von der Karte selbst schon unterstützt wird oder nicht. Das ist vorteilhaft, weil ich dann z.B. zum Lesen eines FAT16 Verzeichniseintrags, der nur 32 Byte groß ist, mich nicht um die Eigenheiten des Speichermediums kümmern muss und so dieser Code Hardware-unabhängig wird. Es ist also Aufgabe der Abstraktion, sich um die niederen Dinge wie Einschränkungen der Hardware zu kümmern. Im extremen Fall, dass man sich die 512 Byte Puffer sparen will, bringt dies natürlich Einbußen in der Performance mit. Dafür ist der Code dann aber auch extrem klein und genügsam. Benutzt man aber diesen Puffer, erhält man bessere Performance und es genügt beim sequentiellen Lesen ein einfaches memcpy, um die Anfrage auszuführen. Ein weiteres Kapitel ist natürlich der Schreibzugriff. Wenn ich auch dies von beliebigen Offsets aus zulassen will, benötige ich zwingend einen Puffer, um den Teil des Blocks, der nicht überschrieben wird, mit den neuen Daten zusammenzufügen. Die Tatsache, dass dies von den MMC/SD-Routinen übernommen wird, vereinfacht wiederum den Code in den höheren Ebenen. Denn, um beim Beispiel zu bleiben, der FAT16-Code muss sich dann eben nicht mehr darum kümmern, die 32 Byte für einen neuen Verzeichniseintrag mit dem vorhandenen 512 Byte-Block auf der Karte zusammenzufügen. Aus seiner Sicht überschreibt er einfach die alten 32 Byte mit den neuen 32 Byte. Und wenn es um hohe Transferraten geht, dann spendiere ich ein bisschen mehr RAM, und schon kann ich z.B. 4 kB auf einen Schlag lesen, und die MMC/SD-Funktionen kümmern sich um die Aufteilung in einzelne 512 Byte-Anfragen an die Karte.
Datum:
Hallo, in den Thread hat sich zwar schon ne weils nichts getan hoffe aber trotzdem auf ne Antwort. Ich bin auch grad dabei ne SD-Karte über SPI anzusteuern. Als erstes sende ich an die Karte 10mal 0xff und dann das Kommando 0x40,0x00,0x00,0x00,0x00,0x95 (CMD 0) alles in 8bit Blöcken. Danach polle ich mit 0xff um die Antwort von der SD-Karte zu bekommen. Normalerweise müste ich doch nun nach dem CRC irgendwann eine 0x01 von der Karte zurückbekommen. Komisch ist das die SD-Karte schon ab dem vierten 0x00 Block des Kommandos,immer mit 0xFE und gleich dannach mit 0x03 antwortet. Dann bekomme ich 2-3 Blöcke garnichts und dann die erwartete 0x01. Kann jemand die Signale deuten? Kann ich die 0xFE und 0x03 ignorieren oder ist das ein Error Code? Danke im vorraus!! Mfg Peter Baumann
Datum:
Hallo Peter, Auf Anhieb kann ich mit dem von Dir beobachteten Verhalten auch nichts anfangen. Wichtig ist, dass Du der Karte nach dem Anlegen der Spannung ein paar Takte Zeit gibst, um sich selbst zu initialisieren. Das kannst Du machen, indem Du beispielsweise 10x 0xff sendest. Erst dann sendest Du CMD0. Wie bei jedem R1-Befehl ist das erste Byte, das ungleich 0xff zurückkommt, Deine Antwort. Danach solltest Du der Karte nochmal ein paar Takte Zeit geben, um intern weiterarbeiten zu können. Ich polle dann ein paar Mal das Busy-Bit in der Antwort auf CMD1, um zu warten, bis die Karte fertig ist. Schau Dir doch mal meinen Code an, den ich auf meiner Homepage oder hier in diesem Thread gepostet habe. In der Datei sd_raw.c steht eigentlich alles drin, was Du brauchst. Den Code habe ich allerdings noch nicht mit vielen Karten testen können. Mit meiner funktioniert er aber. Gruß, Roland
Datum:
Angehängte Dateien:Hi zusammen, Ich habe eine neue Version auf http://www.roland-riegel.de/sd-reader/ zur Verfügung gestellt. Die ZIP-Datei habe ich auch an dieses Posting angehängt. Verbesserungen sind unter anderem: - sehr viel zuverlässigere Karteninitialisierung - viele Geschwindigkeitsverbesserungen - Superfloppy-Unterstützung - bessere Überprüfung des FAT16-Dateisystems beim Öffnen - Fehler beim Vergrößern von Dateien behoben - Fehler beim Anlegen einer Datei >31 Buchstaben beseitigt - viele andere Dinge Viele Grüße, Roland
Datum:
Kann ich damit schnell an das Ende einer Datei springen. Ich möchte MP3 tags auslesen, und die stehen am Ende der Datei (und die haben 200MB)
Datum:
Hallo Gernot, Ja das sollte möglich sein. Bzgl. der Geschwindigkeit müsstest Du das einfach mal ausprobieren, 200MB sind ja viele tausend Cluster und das könnte schon einige Zeit in Anspruch nehmen. Ich selbst habe das noch nicht ausprobiert. Gruß, Roland
Datum:
Muss ich testen. Ich am besten einen ATmega32 mit 16MHz, oder? Kannst Du einen Ausdruck von der Platine dazulegen - als png oder so? Ich hab das Programm nicht, mit dem Du das gemacht hast.
Datum:
Angehängte Dateien:So, bitteschön. Siehe Anhang. Du musst Dir aber zum Testen nicht gleich eine eigene Platine herstellen. Die Schaltung kannst Du auch auf einem Steckbrett aufbauen. Beachte aber bitte, dass die einfachen Spannungsteiler und die zwei Dioden zum Bereitstellen der Betriebsspannung für die Karte keine optimale Lösung sind, durch die einzelne Karten eventuell nicht zuverlässig arbeiten oder sogar beschädigt werden könnten. Besser wäre ein eigener Spannungsregler sowie vernünftige Pegelkonverter für den SPI-Bus. Roland
Datum:
Hallo, ich versuche gerade, den sd-reader mit einem ATmega32 zu betreiben. Muss ich dann in SD_RAW_CONFIG.H Änderungen vornehmen, da hier MOSI, MISO etc. an anderen Pins liegen? Ich bin mir nicht ganz sicher, weil irgenwo steht, es würde genügen im Makefile eine entsprechende Änderung vorzunehmen. In SD_RAW_CONFIG.H steht aber explizit zB. #define configure_pin_mosi() DDRB |= (1 << DDB3). Beim Mega32 ist MOSI aber an Pin 5. Bitte um Aufklärung für einen Anfänger. Malte
Datum:
Hallo Malte, Wenn Du die neue Version des sd-reader von vor zwei Tagen verwendest, sollten die Pins für den SPI-Bus bereits stimmen. Daneben solltest Du aber noch je nach Möglichkeiten Deines Karten-Slots die folgenden #defines ändern: #define configure_pin_available() DDRC &= ~(1 << DDC4) #define configure_pin_locked() DDRC &= ~(1 << DDC5) #define get_pin_available() ((PINC >> PC4) & 0x01) #define get_pin_locked() ((PINC >> PC5) & 0x01) Wenn Dein Slot keine Pins zum Detektieren einer Karte bzw. der Position des Schreibschutzschalters hat, änderst Du diese ab zu: #define configure_pin_available() #define configure_pin_locked() #define get_pin_available() 0 #define get_pin_locked() 0 Im Makefile änderst Du folgende Zeilen passend ab: MCU := atmega168 MCU_AVRDUDE := m168 MCU_FREQ := 16000000UL Das sollte dann alles sein. Roland
Datum:
Hallo Roland, ok, alles klar, ich hatte die alte Version. Danke Malte
Datum:
Hallo, ich krige die SD Karte nicht zum laufen. Bereits beim card-reset in sd_raw_init() kommt ein Abbruch. Kann es daran liegen, dass ich eine miniSD Karte (mit Adapter) verwende? Ansonsten habe ich einen 3.3V Spannungsregler und Widerstände für die Pegelanpassung. Noch eine Frage: Kann ich den AVRISPmkII Programmieradapter eigentlich beim Testen dranlassen, oder stört er die SPI Kommunikation? Ist sonst noch was zu beachten, spezielle Fuses oder so? Gruß Malte
Datum:
Malte
Auch ich habe eine Mega32, bei mir läuft's.
Der Programmier-Adapter stört bei mir bei einigen SD-Karten, nicht bei
allen. Und beim Flashen des Mega ziehe ich immer vorsichtshalber die
Karte raus.
Eine MiniSD-Karte sollte eigentlich kein Problem sein und der
3,3V-Regler ist das beste was Du machen konntest. Die Dioden-Lösung ist
nach meiner Erfahrung sehr unzuverläßig.
Baue doch einfach einige Debug-Meldungen in den Code ein. Man kann
sonst immer so schlecht sehen was wirklich passiert. z.B. mit einfachen
Meldungen die Du dann auf der seriellen Schnittstelle sehen kannst. So
etwa in sd_raw.c:
if(!sd_raw_available())
{
printf_P(PSTR("Error: sd_raw_available\n"));
return 0;
}
usw.
Platz hast Du ja im Mega32 vorerst reichlich zur Fehlersuche.
Spezielle Fuse verwende ich nicht, außer für den ext. Quarz.
Torsten
Datum:
Gernot >..schnell an das Ende einer Datei springen. Nachdem Roland das Buffering überarbeitet hat ist das kein Problem mehr und blitzschnell. Mit der eingebauten Mini-Shell kann man das sehr elegant selbst überprüfen, z.B. so: Datei anlegen: touch 1.txt Datei auf 100MB erweitern und ein paar Zeichen reinschreiben: write 1.txt 100000000 <abcd Oder einfach mitten rein: write 1.txt 50000000 <1234 Beim drücken von Enter spüre ich keine Verzögerung. Das gilt für Schreiben, Lesen sollte schneller möglich sein. Mein Test-Aufbau: Mega32 @ 14,7456MHz, NoName 1GB SD-Karte, 115kB am Uart. OT: MP3's mit 200MB, uff. Das sind keine Songs mehr, etwa Hörbücher o.ä.? Torsten
Datum:
@ Malte Zusätzlich zu den Antworten von Torsten noch drei Anmerkungen: - Die Karte kann während der Programmierung im Slot steckenbleiben, falls Du das /SS-Signal über den Mikroprozessor steuerst. Hast Du das Signal jedoch fest auf Masse gelegt, wird während der Programmierung gleichzeitig die SD-Karte angesprochen, die das wohl nicht mag. Zudem dürfte sie durch vermeintliche Antworten auch aktiv den Programmiervorgang stören. - Da Du einen 3,3V-Regler verwendest, solltest Du drauf achten, dass die Spannungsteiler bei logischem High-Pegel auf keinen Fall mehr, besser etwas weniger als 3,3V an die Karte anlegen. Ich weiß nicht, wie die Karte auf Spannungspegel reagiert, die höher als die Betriebsspannung liegen. - Achte darauf für die MISO-Leitung keinen Spannungsteiler zu verwenden, da dies ein Eingang am Mikrocontroller ist. Die 3,3V der Karte werden bei 5V Betriebsspannung des ATmega noch als High-Pegel erkannt. Gruß, Roland
Datum:
@ Torsten, Roland
danke für die Tips. Ich bin gerade beim Debuggen. Dabei ist mir
aufgefallen, dass in sd_raw_config.h noch folgende Einträge stehen, die
nicht durch ein 'if defined' dem entsprechenden Controllertyp
angepasst werden:
#define select_card() PORTB &= ~(1 << PB2)
#define unselect_card() PORTB |= (1 << PB2)
Beim mega8 ist PB2=SS, beim mega32 ist SS an PB4. Eine entprechende
Änderung bringt aber auch nichts. Mache ich einen Denkfehler?
Die folgende Schleife in sd_raw_init bringt nur 0x00 Werte:
/* card needs 74 cycles minimum to start up */
for(uint8_t i = 0; i < 10; ++i)
{
/* wait 8 clock cycles */
uart_putc(sd_raw_rec_byte());
//sd_raw_rec_byte();
}
Die darauffolgende Schleife mit 'response' bringt 512 mal 0x00.
Kann man daraus schon schliessen, dass etwas grundsätzliches nicht
stimmt?
Gruß
Malte
Datum:
Ich habe gerade festgestellt, dass am CLK Eingang meiner Karte konstant 2.65V anliegen. Hinter dem 1.8k Widerstand, also am SCK Ausgang des Controllers, kann ich dagegen während der Initialisierungsphase ein Taktsignal messen. Die 2.65V sind offenbar so niederohmig, dass das Taktsignal nicht "durchkommt". Wie kann das sein? Gruß Malte
Datum:
Angehängte Dateien:Hallo Malte, Bzgl. der beiden #defines hast Du Recht, die müssen jeweils an die MCU angepasst werden. Eine aktualisierte Version habe ich angehängt. Mit Deiner Schleifenausgabe stimmt tatsächlich etwas nicht. Könntest Du mal ein Foto oder besser noch einen Schaltplan von Deinem Aufbau posten? Sonst ist das alles ziemlich viel Raterei. Wenn Du die Spannungsteiler so aufgebaut hast, wie in meiner Schaltung bzw. der von Ulrich Radig, sollte das schon stimmen. Auf der CLK-Leitung liegt nur ein Takt, während Daten in die ein oder andere Richtung übertragen werden. Danach wird er wieder abgestellt. Der Takt ist zudem so schnell, dass Du ihn nur mit einem Oszilloskop und nicht mit einem gewöhnlichen Voltmeter messen kannst. Die Initialisierung läuft für gewöhnlich innerhalb von wenigen Millisekunden ab, auf einem Voltmeter erkennst Du da überhaupt nichts. Roland
Datum:
Hallo Roland, ich hatte vergessen zu schreiben, dass ich das Taktsignal mit dem Oszi gemessen habe. Und, wie gesagt, am SCK-Pin des Controllers liegt es eine knappe Sekunde lang an (viel länger als wenige Millisekunden???). Direkt an der Karte, hinter dem Widerstand ist aber nix mehr vom Takt da, nur Gleichspannung. Die Spannungsteiler habe ich genau so wie du und Ulrich aufgebaut, die Pegel stimmen sonst auch (etwas unter VCC). Ich mache mal einen Schaltplan... Danke und Gruß Malte
Datum:
Angehängte Dateien:...hier der Schaltplan. Ich habe keien Eagle-Vorlage für den Mega32, der Mega163 hat aber die gleiche Belegung.
Datum:
Asche auf mein Haupt! Ich habe die Pin-Nummern der Karte verwechselt, da der 9te Pin ausser der Reihe liegt. Ich Trott.. Immerhin musste ich mich so etwas intensiver mit der Materie beschäftigen und habe dabei eine Menge gelernt. Danke noch mal für die Hilfe
Datum:
Hallo Malte! Heißt das, dass es jetzt bei Dir funktioniert? Herzlichen Glückwunsch! Naja, immerhin hast Du jetzt schon mal einen Schaltplan, auf dem Du aufbauen kannst... ;-) Roland
Datum:
Hallo Roland, ja, es funktionierte auf Anhieb. Klasse Software, dein reader! Habe noch folgendes festgestellt: Wenn man eine Datei erstellt, etwas reinschreibt, die Datei dann löscht und danach eine neue Datei mit gleichem Namen erstellt, steht wieder der alte Inhalt drin. Richtig? Gruß Malte
Datum:
kommt von dos. wenn du eine datei löscht, wird nur der name herausgenommen, wenn dir der gleiche name wieder einfällt und dort reinschreibst, kannste die datei wieder herstellen.
Datum:
Hallo Malte, Der alte Inhalt steht aber nur drin, wenn die Größe der neuen Datei > 0 ist, oder? Sonst würde da was nicht stimmen. Das Verhalten ist ok. Hat aber nicht unbedingt etwas mit DOS zu tun, sondern eher mit Geschwindigkeit. Da ich die FAT sequentiell nach freien Clustern durchsuche, allokiere ich für die Datei denselben Cluster, den die zuvor gelöschte Datei benutzt hat. Um die Geschwindigkeit hoch zu halten, verzichte ich darauf, beim Vergrößern der Datei die Cluster zu nullen. Bei Bedarf musst Du das Datenleck selbst schließen und den Cluster leeren. In der Doku der Funktion fat16_resize_file() steht das auch nochmal. Gruß, Roland
Datum:
Hallo Roland,
Ich habe gerade den Samstag damit verbracht ein kleines Board für den
Kartenslot und eine Testplatine für meinen Mega16 zu Bauen.
Ich kann jetzt von einer 128 MB SD-Karte eine Datei, dumpen.
Vielen Dank. Großartige Arbeit.
Auf meinen Mega88 hat das Image mit dem Test-Main leider nicht
raufgepasst, auch nicht nachdem ich ein bisschen was wegdefiniert
habe.
Und ich denke der Mega 16 hat jetzt auch nicht mehr viel Luft für neuen
Code, ich werde einen Mega32 Ordern.
Ich habe noch eine 16MB-Karte, die kann das Programm aber nicht lesen.
Ich würde mir noch ein paar Zeilen Doku zu dem Main wünschen, und ein
paar grundsätzliche Hinweise zur Inbetriebsetzung.
Aber nochmal danke und klasse Arbeit.
servus
Dirk
Datum:
Hallo Roland,
noch ein paar Fragen zu deinen Schreibfunktionen:
Ich will den SD-Karte in einem Datenlogger einsetzen, der ständig
läuft. Es kommen pro Sekunde etwa 600 byte, die in Blöcken zu 512 byte
(oder mehr??) auf die Karte geschrieben werden sollen. Einmal pro Tag
wird eine neue Datei angelegt ("Tagesfiles"). Das ergibt eine Größe
von gut 5MB/Tag.
Muss man beim Schreiben ans Ende einer bestehenden Datei die Datei
vorher vergrößern (resize), oder wird die Größe beim Schreiben
automatisch angepasst?
Muss man für jeden Block die Datei öffnen und wieder schliessen, oder
kann man sie offen lassen? Oder nach jedem Schreiben ein sd_raw_sync
machen? Was bewirkt eigentlich das Schliessen der Datei, wird da noch
was in die FAT geschrieben?
Im Falle eines Stromausfalls wäre es nicht gut, wenn der gesamte
bisherige Tagesfile verloren wäre. Wie muss ich vorgehen, um dem
vorzubeugen / den Datenverlust zu minimieren? Bei DOS entsteht in
solchen Fällen bei noch geöffneten Dateien ja ziemlicher Murks.
Wie kann ich eine Funktion zur Ermittlung des verbleibenden
Speicherplatzes auf der Karte realisieren?
Beste Grüße
Malte
Datum:
@Dirk Schön, dass es funktioniert. So wie das Programm im Download konfiguriert ist passt es tatsächlich nicht mehr in 8kByte. Wenn man jedoch nur den Lese-Support benötigt und sd_raw_config.h bzw. fat16.h dementsprechend abändert, sollte ein einfaches Programm auf einem mega8 durchaus zu realisieren sein. Und was den mega16 angeht solltest Du mal den recht umfangreichen Code in main.c durch Deinen eigenen ersetzen. Ich weiß zwar nicht, was Du mit der SD-Unterstützung vorhast, aber solang Du nicht wesentlich mehr RAM brauchst, ist die Benutzung eines mega16 schon möglich. Benutzt Du die Optimierungsmöglichkeiten Deines Compilers? Könntest Du mir erläutern, welche zusätzliche Doku Du benötigst? Ich dachte eigentlich, die main()-Funktion wäre als Beispielanwendung weitgehend selbsterklärend. Die Dokumentation für die SD-, Partitions- und FAT16-Funktionen hast Du ja sicherlich schon im doc-Verzeichnis oder auf meiner Homepage entdeckt.
Datum:
@Malte Die von Dir zu schreibenden Daten werden vom sd_raw-Code automatisch in 512-Byte-Blöcke aufgeteilt. Du kannst Daten beliebiger Größe schreiben oder lesen. Wenn Du allerdings jede Sekunde schreiben willst, kann dies zu Lasten der Lebensdauer der Karte führen. Du solltest daher eventuell in einem eigenen Puffer die Log-Daten sammeln und in einem Rutsch auf die Karte schreiben. Die von mir implementierte Schreibpufferung lindert dieses Problem zwar, jedoch ist ein schreibender Dateizugriff relativ komplex, sodass diese Pufferung nicht optimal greift. Du kannst die Dateien zu beliebigem Zeitpunkt öffnen oder schließen. Es sind beliebig viele Zugriffe in beliebig großen Zeitabständen möglich, ohne die Datei zwischendurch zu schließen. Wenn Du über das Ende einer Datei hinausschreibst, wird diese automatisch vergrößert. Du kannst auch fat16_seek_file() benutzen, um die Schreibposition innerhalb der Datei festzulegen. Auch diese Funktion ruft bei Bedarf fat16_resize_file() implizit auf. Wenn die Schreibpufferung aktiviert ist, sollte nach umfangreichen Zugriffen oder auch in einem regelmäßigen Zeitintervall sd_raw_sync() aufgerufen werden, um die Konsistenz der Daten und des Dateisystems zu gewährleisten. Danach kann die Karte abgezogen werden. sd_raw_sync() aufzurufen, während Dateien geöffnet sind, ist problemlos möglich. Die Ermittlung des freien Speicherplatzes ist relativ einfach möglich, man durchläuft dazu die FAT und zählt die freien Cluster. Bei Gelegenheit werde ich das mal implementieren. Gruß, Roland
Datum:
@Roland:
Doku benötigen wäre sicher etwas zuviel gesagt.
Du hättest vieleicht noch erläutern können, welche PortPins du mit
welchen an der Karte verbunden hast, insbesondere SS. Ebenso könnte man
beschreiben, welche Einstellungen für das Terminalprogramm zu wählen
sind, für das Testmain. Aber das bleibt dir überlassen und steht
schliesslich alles im Code drin. Ein Chef von mir hat mal früher
gesagt: Der Code ist die Doku.
Ebenso ein Vorschlag, was man mit der Shell anstellen kann, wie oben in
einem Beitrag:
touch 1.txt
write 1.txt 1000
ls
...
Vieleicht noch ein Warnhinweis, daß Backspace im Terminalprogramm evtl.
nicht so gut Tippfehler korrigiert, wie man denkt. Space am Ende von
Dateinamen,...
Aber das ist vieleicht mein persönliches Trauma. Konzentrier' dich,
auf was dir wichtig erscheint und lass dich nicht von mir davon
abhalten tolle Sachen zu machen.
Wirst du den Code noch weiterpflegen?
Gibt es noch known-bugs, mit Dateien, die sich überschreiben, oder
Karten, die Probleme bereiten?
Gruß
Dirk
Datum:
@Roland: Ich schliesse aus deinen Aussagen, dass ich noch einen externen RAM verwenden sollte. Ich werde mir mal das Projekt von Benedikt http://www.mikrocontroller.net/forum/read-4-121457.html ansehen. Du schreibst, dass man sd_raw_sync() auch bei geöffneter Datei aufrufen kann. Bedeutet dies, dass bei einem Stromausfall alles, was vor dem letzten Aufruf von sd_raw_sync() geschrieben wurde, erhalten bleibt, auch wenn die Datei beim Ausfall geöffnet war? Das wäre natürlich sehr komfortabel. @Dirk: auf Rolands Homepage ist ein Eagle Schaltplan. Als Terminal Programm (für Windows) habe ich sehr gute Erfahrungen mit Hterm (http://www.der-hammer.info/terminal/) gemacht. Gruß Malte
Datum:
@Dirk Ich werde mal schauen, was von den genannten Sachen noch sinnvoll wäre aufzunehmen. Danke für die Anregungen. @Malte Viel RAM ist immer gut, zumindest bei Sachen wie Dateisystemen. Da könnte man dann die ganze FAT, das Root Directory und vieles mehr zwischenpuffern. Leider ist es aber mit den von Benedikt verwendeten Speichergrößen nicht mehr möglich, den Speicher direkt zu adressieren. Das verkompliziert den Speicherzugriff schon erheblich. Bzgl. sd_raw_sync() hast Du Recht. Schließlich heißt die Funktion ja auch so... Als Terminalprogramm verwende ich unter Debian cu. Das hat wenigstens kein nerviges Fenster sondern läuft in der Konsole :-) Grüße, Roland
Datum:
Hallo Roland, sorry wegen der vielen Fragen. Ich bin, was Controller angeht, noch ein totaler Anfänger. Die Kiste läuft aber trotzdem schon ziemlich gut, dank der vielen Hilfen aus diesem Forum. Ich wollte mit dem RAM gar nicht in die Dateiverwaltung eingreifen, sondern einfach nur zB. 64kB Meßdaten zwischenspeichern und dann in einem Rutsch auf die Karte schreiben. Wäre das bei Verwendung deiner jetzigen Software sinnvoll? Falls ja, wie kann man das möglichst einfach realisieren? Kennst du vielleicht eine gute Quelle für so ein (wahrscheinlich relativ alltägliches) Projekt mit dem Mega32? Ich recherchiere schon seit einiger Zeit, habe aber noch nichts passendes gefunden. Gruß Malte
Datum:
Hi Malte, Die 64k würden schon helfen, aber die Lösung ist das wohl nicht. Bei 600B/s wäre das ein Schreibzugriff alle 100s. Nach 12 Tagen sind 10000 Schreibzyklen in dem Verzeichniseintrag erreicht. Und das dürfte auch das Ende der SD-Karte sein. Hmm, Moment mal. Wenn Du zu Beginn die Datei direkt auf 5MB aufbläst (mit fat16_resize_file()) und dann vom Dateianfang aus reinschreibst, muss der Verzeichniseintrag nicht aktualisiert werden. Dann sollte die Karte wesentlich länger durchhalten. Bis demnächst, Roland
Datum:
Was ihr nur alle mit den 10000 Schreibzyklen habt. Ein SD-Card hat einen internen Controller wenn ein Sektor nicht mehr schreibbar ist wird der durch einen Ersatzsektor ausgetauscht. Wieviele solche Ersatzsektoren vorhanden sind ist Sache der Hersteller und dürfte sich auch im Preis wiederspiegeln. Eine SD-Karte hat auch einen internen RAM ,das merkt man am schnelleren Multisektorzugriff. Da werden die Daten auch erstmal gesammelt. Ausserdem schafft flash heutzutage 100.000 Zyklen. Wenn es unbedingt Langzeit sein muss, nimmt man ein FRAM sammelt da die Daten und schreibt am Block.
Datum:
Eben, die Anzahl der Ersatzsektoren kommt auf den Hersteller an. Bei den zur Zeit zu Schleuderpreisen angebotenen Karten handelt es sich ja oft um Billig-Hersteller. Die werden an der Stelle bestimmt sparen. Ich habe mir bereits eine Karte abgeschossen, sie ist jetzt dauerhaft schreibgeschützt. Ob das durch zu viele Schreibvorgänge während der Entwicklung des sd-reader geschehen ist kann ich nicht mit Bestimmtheit sagen, aber es ist meine Vermutung. Ich denke, wenn es mit wenig Aufwand möglich ist, den Flash zu schonen, dann sollte man das auch tun. Zumindest beim in meinem Code verwendeten Einzel-Blockzugriff wird durch die Karte nicht gepuffert, da man dann ja Datenverlust beim Abziehen der Karte zu befürchten hätte. Roland
Datum:
>Die werden an der Stelle bestimmt sparen. Ich >habe mir bereits eine Karte abgeschossen, sie ist jetzt dauerhaft >schreibgeschützt. Ob das durch zu viele Schreibvorgänge während der >Entwicklung des sd-reader geschehen ist kann ich nicht mit Bestimmtheit >sagen, aber es ist meine Vermutung. Ich denke eher du hast irgendein (nicht dokumentiertes?) Register beschrieben beim testen... Ich hab beim testen mit meinem Code extreMEmory Karten zerschossen (reproduzierbar :-X). Hab jetzt zwei Karten wo nur noch der SPI Modus geht, MMC modus = keine Reaktion. Und das obwohl die Karten im Betrieb deselektiert waren (CS=high und dann ein §65 Display per SPI mit vielen Daten beschrieben -> mmc karte tot). Da vermute ich irgendeinen Bug in der mc karten statemachine oder so... Kanns mir sonst nicht erklären. Bei uralten 32MB mmc karten passiert das nicht :) Bye, Simon
Datum:
@Roland: wie ich sehe versuchst du das FAT16 Dateisystem an dem String FAT16 zu erkennen, dies ist ein Eintrag in dem auch andere Sachen stehen können und er ist nicht obligatorisch für FAT16. Das Windowsformatprogramm macht dies allerdings seit Jahren so.
Datum:
Ja stimmt, das ist nicht eindeutig. Aber es ist üblich, und eine einfach zu implementierende Möglichkeit. Es gibt mehrere Stellen, an denen diese Zeichenkette stehen kann. Ich will damit eigentlich nur Datenverlust vermeiden in dem Fall, dass ein Sektor fälschlicherweise als FAT16-Header interpretiert wird. Den Zweck erfüllt es auch, denke ich. Hast Du eine bessere Idee? Roland
Datum:
55AA prüfen, auf Partitionssektor prüfen Bootsektor 55AA prüfen Clusteranzahl<4085 ||Clusteranzahl>65524 Sektoren pro Cluster 2^n ? evt. anfang der FAT cluster 0 und 1 Wert prüfen Bevor Microsoft die FAT Patente bekam gab es von Microsoft ein Dokument das aus der Einführungszeit von VFAT stammt und unterschiedliche FATimplementierungen und testroutinen (unter anderen Norton und PCTools) und mögliche Auswirkungen durch VFAT diskutiert. Ausserdem wird auf typische Fehler in anderen FATimplementierungen eingegegangen. Hier wird nochmals ausdrücklich darauf hingewiesen das FAT12 und FAT16 nicht durch den String sondern allein durch die Clusteranzahl auseinandergehalten werden. Auch PCIntern hat in der Bootsektorbeschreibung diesen String nicht als obligatorisch. Bezüglich Datenverlust: schon beim Einlesen des Hauptverzeichnisses dürfte es probleme geben.
Datum:
Danke für die Anregungen. Ich halte Deine Ansätze aber für ziemlich Code-intensiv. Denn es sind mehrere Lesevorgänge erforderlich, Zusammenbauen der 16-Bit-Werte, das Prüfen der Werte, usw. Trotzdem, hast Du vielleicht noch einen Link zu dem von Dir erwähnten Microsoft-Dokument? Ich habe das mit kurzer Suche nicht mehr finden können. Danke und Gruß, Roland
Datum:
>Denn es sind mehrere Lesevorgänge erforderlich, 1. Sektor laden Partitionssektor? wenn ja Bootsektor laden >Zusammenbauen der 16-Bit-Werte, das Prüfen der Werte, usw. Diese Werte musst du sowieso auslesen und das Zusammenbauen aus 8Bitwerten solltest du sowieso machen wenn du Interesse daran hast das dein FAT-Code auch auf anderen CPU läuft. >Trotzdem, hast Du vielleicht noch einen Link... Dieses Dokument ist aus dem Netz verschwunden als Microsoft die FAT-Patente erhalten hat. Ich muss mal suchen ob ich es noch finde. BTW: Hast du dir schonmal Gedanken gemacht was passiert wenn Microsoft an dich herantritt wegen der FAT-Implementierung?
Datum:
Im Prinzip hast Du Recht. Wenn Du Dir meinen Code anschaust, siehst Du, dass ich nur die Bereiche aus dem MBR bzw. dem Partitionssektor lade, die mich für die Anwendung wirklich interessieren. Auf meinem mega168 ist RAM sehr knapp (und Flash bald auch), ich hatte mehrfach Probleme mit Kollisionen zwischen Heap und Stack. Deswegen will ich mir keine teuren Überprüfungen leisten. Ganz zu schweigen von Sektoren, die ich der Einfachkeit wegen komplett auf einen Schlag ins RAM lade. Im Übrigen sollte der Code schon plattformunabhängig sein. Alle multi-Byte-Werte baue ich einzeln zusammen, um nicht auf die Endianess der MCU angewiesen zu sein. Was Microsoft angeht denke ich, dass ich nicht der erste bin, der FAT16-Unterstützung implementiert. Mein Code basiert komplett auf Informationen, die bereits öffentlich im Internet zu finden sind. Wenn mich Microsoft ansprechen sollte, werde ich das Projekt natürlich sofort von meiner Seite entfernen.
Datum:
Angehängte Dateien:@alle Ich habe nochmal eine neue Version auf http://www.roland-riegel.de/sd-reader/ bereitgestellt und auch an dieses Posting gehängt. Die Neuerungen sind: - Zwei Funktionen, die die Größe des gesamten und des freien Speicherplatzes berechnen. - Unterstützung der Backspace-Taste in der Mini-Shell. - Aktivierung des Idle-Mode beim Warten auf die UART. - Kurz-Dokumentation der Mini-Shell-Befehle. - (un)select_card() ist nun auch MCU-abhängig. Gruß, Roland
Datum:
>Im Übrigen sollte der Code schon plattformunabhängig sein.
Ein Tip aus eigener Erfahrung, du hast sowieso nur eine Lese-/Schreib
und Kartendetektionsroutine. Der Rest sollte Hardwareunabhängig sein.
Wenn du die genannten Routine auf dem PC in eine Datei/Device umlenkst
kannst du alles auf dem PC entwickeln, aufgrund der erweiterten
Debuggingmöglichkeiten auf dem PC geht es wesentlich schneller voran
und es wird mit Sicherheit plattformunabhängig. Ganz nebenbei schont es
den flash der MCU und der SDCard.
Datum:
Hallo Wolfram, Ganz zu Beginn hatte ich das schon so gemacht. Ich habe mir ein Image der SD-Karte gezogen und auf dem PC mittels fopen(), fread() und fclose() darauf zugegriffen. Als ich dann Dateien in dem Image auflisten und dumpen konnte sowie in Verzeichnisse wechseln konnte, bin ich dann auf den AVR umgestiegen. Gruß, Roland
Datum:
@Roland: Ich habe zumindest das eine Dokument im Netz gefunden: http://www.walrus.com/~raphael/pdf/FatFormat.pdf#s...
Datum:
Hallo Wolfram, Danke, dass Du das noch auftreiben konntest. Werde ich mir bei Gelegenheit mal durchschauen. Vielleicht findet sich ja noch das ein oder andere Detail, dass ich anders oder sogar falsch implementiert habe. Gruß, Roland
Datum:
Hi! Wenn ich mich nicht verlesen habe so erkennt man die Fatart auch an den 1ten Byte jeder Fat. $0FF8 = Fat 12 $FFF8 = Fat 16 $0FFFFFF8 = Fat 32 oder Offset Description Size 000h Executable Code (Boots Computer) 446 Bytes 1BEh 1st Partition Entry (See Next Table) 16 Bytes 1CEh 2nd Partition Entry 16 Bytes 1DEh 3rd Partition Entry 16 Bytes 1EEh 4th Partition Entry 16 Bytes 1FEh Boot Record Signature (55h AAh) 2 Bytes Partition Entry (Part of MBR) Offset Description Size 00h Current State of Partition (00h=Inactive, 80h=Active) 1 Byte 01h Beginning of Partition - Head 1 Byte 02h Beginning of Partition - Cylinder/Sector (See Below) 1 Word 04h Type of Partition (See List Below) 1 Byte 05h End of Partition - Head 1 Byte 06h End of Partition - Cylinder/Sector 1 Word 08h Number of Sectors Between the MBR and the First Sector in the Partition 1 Double Word 0Ch Number of Sectors in the Partition 1 Double Word Partition Type Listing There are more than just these shown, but I've only included that ones relevant to MS Operating Systems. Value Description 00h Unknown or Nothing 01h 12-bit FAT 04h 16-bit FAT (Partition Smaller than 32MB) 05h Extended MS-DOS Partition 06h 16-bit FAT (Partition Larger than 32MB) 0Bh 32-bit FAT (Partition Up to 2048GB) 0Ch Same as 0BH, but uses LBA1 13h Extensions 0Eh Same as 06H, but uses LBA1 13h Extensions 0Fh Same as 05H, but uses LBA1 13h Extensions Die Fatstartadresse musst du sowiso berechnen, da kannste den Sector auch mal lesen. Wenn du es dann noch mit dem MBReintrag vergleichst sollte das eigentlich recht sicher sein. Du kannst natürlich auch die VBReinträge prüfen und aus der Clusterzahl auf die Fat schließen. schönen Tag noch, Uwe
Datum:
@Uwe Die ersten zwei Bytes der FAT auszuwerten ist aber wohl auch bloß ein Notbehelf. Zudem wäre es noch durchaus denkbar, dass diese zwei Bytes zufällig korrekte Werte haben, der Datenträger in Wirklichkeit aber ganz was anderes als FAT16 enthält. Inzwischen habe ich die von Wolfram vorgeschlagene Unterscheidung anhand der Datenclusteranzahl implementiert. Dies wird im Microsoft-Paper sogar als einzig richtige Methode dargestellt. @alle Dadurch konnte ich auch gleich noch einen anderen Fehler beheben. Mein Code ging bisher davon aus, dass die FAT immer an einer Sektorgrenze endet. Daher konnte es vorkommen, dass bei nahezu voller Karte Cluster über die Kartengröße hinaus allokiert wurden. Den korrigierten Code werde ich wohl noch diese Woche hier posten. Gruß, Roland
Datum:
Moin, erstmal Glückwunsch zu dem Projekt und Danke an alle, die sich hier richtig reinhängen, speziell an Roland. Ich möchte habe auch ein Projekt, bei dem ich eine SD/MMC als Datenlogger mit einbinden möchte und erstelle gerade das Konzept. Nun meine Frage: Um die Anzahl der Bauelemente und den benötigten Platz klein zu halten, wollte ich den Atmega168 direkt bei 3,3V betreiben und mir den Levelshifter sparen. Bis 10Mhz ist das ja laut Datenblatt zulässig oder habe ich noch was übersehen? Noch eine Bitte: Könnte jemand den Schaltplan mal als PDF, JPG oder PNG posten? Ich habe hier auf Arbeit kein Eagle .... Danke! abo
Datum:
Angehängte Dateien:@Wirus Laut Datenplatt sind 10MHz@3,3V möglich. Achte aber darauf, dass je nach Art auch Dein Programmieradapter die Spannung unterstützen muss. Schaltplan ist angehängt. Gruß, Roland
Datum:
Angehängte Dateien:So, wie angekündigt gibts nochmal eine neue Version auf http://www.roland-riegel.de/sd-reader/ Die wichtigsten Veränderungen sind: - Verbessertes Handling des Idle-Mode. - Anzeige weiterer Kartenparameter beim "disk"-Befehl. Dieser wird jetzt auch beim Start automatisch ausgeführt. - Identifikation von FAT16 anhand der Clusteranzahl. - Mögliche Clusterreservierung über die Kartenkapazität hinaus korrigiert. Quelltext wie immer auch angehängt. Roland
Datum:
Hallo Roland, schönen Dank für die neue Version. Mir ist aufgefallen, dass die disk-funktion nur etwa die Hälfte des tatsächlich freien Speicherplatzes anzeigt. Eine leere 256MB disk zeigt folgendes: manuf: 0x02 oem: TM prod: SD256 rev: 68 serial: 0x707dd547 date: 03/05 size: 255066112 copy: 0 wr.pr.: 0/0 format: 0 free: 120578048/254795776 Unter Windows wird die korrekte Größe angezeigt. Filesystem anlegen und formatieren habe ich unter Linux gemacht (eine unter Windows formatierte disk wurde nicht erkannt). Habe ich beim formatieren vielleicht etwas falsch gemacht? Jedenfalls habe ich bei mkdosfs ausser dem device nichts weiter angegeben. fdisk zeigt 8 Köpfe, 61 Sektoren, 1020 Zylinder. Gruß Malte
Datum:
Hallo Malte!
Zwei mögliche Ursachen fallen mir ein:
- Vor dem Auswerfen der Karte wurde nicht richtig synchronisiert.
(unter Linux mit "eject /dev/sda", i.d.R. aber nicht nötig)
- Windows verwendet die zweite FAT.
Vernünftig erklären kann ich es mir aber eigentlich nicht. Könntest Du
bitte mal unter Linux die ersten 256kByte auf der Karte dumpen und mir
per Mail (feedback@roland-riegel.de) schicken?
Zur Info (Annahme: SD-Karte als /dev/sda):
dd if=/dev/sda1 of=fat.dump bs=16k count=16
Die Datei fat.dump schickst Du mir dann bitte zu. Mal sehen ob uns das
irgendwie weiterhilft.
Gruß,
Roland
Datum:
die kann man auch hier hochladen. Ihr immer mit eurem Email hinundhergeschickte. Dafür ist das Forum nicht da!
Datum:
@Simon Die anderen Teilnehmer wird die FAT von Malte aber kaum interessieren, für sie ist es ja bloß Datenmüll. Oder was sollen Sie Deiner Meinung nach damit anfangen? Roland
Datum:
Ok. Noch eine Sache: die neue Version (0824) funktioniert bei mir leider nicht wenn externe Interrupts benutzt werden. Bei den älteren Versionen hatte ich gar keine Probleme damit. Daher muss ich jetzt erstmal mit der älteren Version (0816) weiterarbeiten. Any idea? Vielleicht irgendwas mit dem Idle-Mode? Gruß Malte
Datum:
Malte Ersetze einfach in "uart.c" #define USE_SLEEP 1 durch #define USE_SLEEP 0 und kommmentiere in der main() in "main.c" folgende Zeile set_sleep_mode(SLEEP_MODE_IDLE); einfach aus. Dann sollte es eigentlich sein wie vorher. Roland hat den Idle-Mode auf meinen ausdrücklichen Wunsch hin eingebaut. Wir haben lange diskutiert wie es am sinnvollsten ist. Nur an einen ext.Interrupt hat keiner gedacht.. Torsten
Datum:
Wie Torsten schon sagt, ist das mit dem Sleep-Mode etwas heikel, und sollte eventuell für ein richtiges Projekt deaktiviert werden. Die ISR für den externen Interrupt sollte zwar schon ausgeführt werden. Wenn Du dort jedoch wie üblich nur ein Flag setzt, welches dann in der main() abgefragt und abgearbeitet wird, gibt es Probleme. Denn uart_getc() wartet immer noch auf das nächste Uart-Zeichen, und die main() kommt nicht zum Zug. Für das Beispiel-Programm auf meiner Homepage mag das Verhalten sinnvoll sein. Für ein anderes Projekt jedoch, wo die MCU noch andere Dinge zu erledigen hat, wohl eher nicht.
Datum:
Welche aufgabe übernimmt eigentlich am avr immer der port ss an der mmc-karte? kann man auch eien anderen port nehmen?
Datum:
Du kannst jeden beliebigen Port-Pin wählen. Die SS- oder auch CS-Leitung dient zur Adressierung der Karte. Wenn diese Leitung auf Low liegt, fühlt sich die Karte angesprochen und reagiert auf Befehle. Ist sie jedoch High, verhält sie sich passiv. Wenn Du am SPI-Bus nur die Karte angeschlossen hast, kannst Du Dir den Pin sparen und den entsprechenden Anschluss der Karte auf Masse legen. Ansonsten jedoch ist er nötig, um die Karte nicht durch den SPI-Verkehr mit anderen Geräten zu stören, und umgekehrt. Einige Chips, wie der ENC28J60, benötigen diese Leitung auch als eine Art "Befehlstakt". In diesem Fall kann die Leitung natürlich nicht eingespart werden.
Datum:
da ich nur die mmc-karte anschliessen möchte und diese auch nur betreibe, kann man den anschluss an der mmc cs sofort auf masse legen?
Datum:
hier sind ja alles fachleute. ich möchte die mmc-karte nicht mit dos und fat betreiben. ich möchte einfach die mmc-karte initialieren und dann 512bytes lesen, schreiben und evtl löschen. wo kann man in winavr-c einfache beispiele ausmachen. ich steige durch den oberen code für die mmc-karte nicht durch, finde als laie keine timing, adressen usw. danke. mfg
Datum:
@Peter Lese Dir doch bitte meine obige Antwort sorgfältig durch, dass sollte Deine erneute Frage bzgl. des CS-Anschlusses der Karte beantworten. Was willst Du denn für die MMC-Ansteuerung über den SPI-Bus für Timing-Parameter oder Adressen wissen? Alles was Du für Deinen Anwendungszweck von meinem Code brauchst, steht in den Dateien sd_raw.c, sd_raw.h und sd_raw_config.h. Den Rest kannst Du weglassen. Mach Dir bitte die Mühe und beschäftige Dich mit dem Code. Im Unterverzeichnis doc/html findest Du nicht umsonst eine ausführliche Dokumentation der erforderlichen Funktionen. Roland
Datum:
Hallo Roland, bin gerade dabei, einen Datenlogger mit einem Mega32 zu bauen und nutze dabei Deinen Code zur Ansteuerung der SD-Karte. Hatte auch null Probleme, den Code einzubinden, ist schön übersichtlich und gut kommentiert (besser als meiner...;-)), echt klasse. Leider sind die Ausführungszeiten mancher Funktionen zu lang, so dass mir (bei höheren Sampleraten) jedes Mal wenn ein Block auf die Karte geschrieben wird, samples verloren gehen, weil zum Beispiel die CPU auf die SD-Karte wartet: while(sd_raw_rec_byte() != 0xff); Ich suche nun nach einer Möglichkeit, diese busy waits zu vermeiden und statt dessen ins Hauptprogramm zurückzukehren, um bei Bedarf weitere Messungen anzutriggern (gemessen wird mit einem MAX127 über TWI). Ich habe schon versucht, statt der Warteschleife ein flag zu setzen und die Warteschleife dann am Anfang des nächsten Aufrufs auszuführen, hat aber nicht geklappt, wahrscheinlich weil nach dem write ein read durchgeführt werden muss, um den nächsten Block zu finden, und die Karte dann noch nicht bereit ist. Ich fürchte, der Code müsste massiv umgeschrieben werden, um hier deutliche Verbesserungen zu erzielen. Wahrscheinlich müsste dann auch Deine elegante Aufteilung in Schichten dran glauben... Irgendwelche Ideen, in welcher Richtung ich hier am schlauesten vorgehen könnte? Gruss, Thorsten
Datum:
Hallo Thorsten! Wie groß ist denn Deine zu erwartende Datenrate, mit der Du auf die Karte schreiben willst? Nutzt Du den FAT16-Treiber, oder schreibst Du im Raw-Format? Die FAT-Schicht verursacht natürlich einiges an Overhead, um das Dateisystem zu verwalten. Bevor Du versuchst, den Code im großen Stil umzuschreiben, solltest Du die maximal mögliche Schreibdatenrate ermitteln. Wenn die Datenrate unter Deinen Anforderungen liegt, müsste man etwas Grundlegendes ändern (MCU-/SPI-Takt, Multi-Block-Writes, usw.). Ich habe noch nicht genau getestet, ob die SD-Karten während des eigentlichen Schreibvorgangs einen SPI-Takt benötigen. Wenn ja, muss die MCU ständig die Karte pollen, um überhaupt den Schreibvorgang abzuschließen. D.h. dann wäre das Busy-Waiting notwendig. Ansonsten könntest Du das Problem mit irgendwelchen Callback-Techniken (wie z.B. in sd_raw_read_interval()), Interrupts oder einem einfachen Multi-Threading lösen. Als alles erschlagende Methode könntest Du auch einen zweiten Controller einsetzen, der ausschließlich die Karte ansteuert und vom ersten Controller die Daten bekommt. Falls Du die Daten bisher in einem menschenlesbaren Format abspeicherst, bringt ein binäres Format auch wesentliche Einsparungen. Je nach Schreibgeschwindigkeit wirst Du wohl auch um eine großzügige Pufferung der Daten nicht herumkommen. Gruß, Roland
Datum:
Hallo Roland und Thorsten, ich habe gerade exakt das gleiche Problem wie Thorsten und probiere schon eine ganze Weile rum. Bei meinem Datenlogger wird alle 2.5ms ein Interrupt ausgelöst, 2 bytes eingelesen und in ein Array geschrieben. Das macht 800B/s. Wenn das Array mit 512 bytes voll ist, wird es auf die Karte geschrieben (mit FAT16). Dieser Schreibvorgang dauert unterschiedlich lang. Normalerweise irgendwas zwischen 2.5 und 5ms, bei jedem achten Schreibvorgang (4096 bytes) aber etwa 5 mal so lange. Bei Puffergröße=256 bytes kommt der langsame Schreibvorgang auch immer nach 4096 bytes (16 x schreiben). Während des Schreibens gehen unregelmäßsig manchmal ein paar Samples verloren. Ich habe auch versucht, immer die jeweils 2 gelesenen bytes direkt innerhalb der ISR auf die Karte zu schreiben. Ohne Erfolg, auch beim schreiben von nur 2 bytes dauert irgendwas zu lange. Übrigens habe ich die zu schreibende Datei vorher mit resize genügend groß gemacht, daher sollte auf der FAT nicht mehr "rumgeorgelt" (O-Ton letzte c't) werden müssen. Dies war ja auch ein Tip von Roland, weiter oben in diesem Thread. Wenn ich den Buffer per UART rausschicke, gibt es keine Probleme. Der Sendevorgang wird zwar dauernd durch Interrupts unterbrochen, es kommt aber alles heil und vollständig an. Einzige Lösung die mir (wie Roland) eingefallen ist, wäre ein zweiter Controller. Bin natürlich interessiert daran, ob ihr den Code noch irgenwie schneller oder anders getimed hinkriegt. Gruß Malte
Datum:
Hallo Roland, Meine erwartete Datenrate sind ca. 20kbytes/s, zur Verwendung kommt ein Binärformat. In reinen Schreibtests mit Deinem FAT16-Treiber konnte ich ca. 60kbytes/s erzielen, sollte also drin sein (mein Mega32 läuft mit 14.7456MHz). Mein Problem ist nicht der absolute Overhead, sondern die Latenzzeit, die auftritt wenn ein Block geschrieben wird. Ich verwende den FAT16-Treiber, da die Karte nach der Messung im PC ausgelesen werden soll. Da meine Datenrate recht konstant ist, bringt ein grösserer Datenpuffer nicht so richtig was (wenn die Daten schneller kommen, als der Prozessor sie wegschreiben kann, geht es halt einfach nicht, egal wie gross der Puffer ist). Ausserdem löst eine geringere Datenrate das Problem nicht, denn die Latenzzeit tritt zwar weniger oft auf, ist jedoch immer noch genauso gross (grösser als mein Samplingintervall). Eventuell könnte ein Puffer für die FAT16-Metadaten etwas bringen? Interrupts könnten auch was bringen, allerdings müssten dann auch FAT16-Routinen in die ISR gepackt werden, sonst wartet dann halt die FAT-Routine statt der sd_raw routine, und ich bin immernoch da, wo ich am Anfang war (daher meine Befürchtung, dass grössere Änderungen am Code nötig werden). Bei f/2 SPI Takt habe ich pro zu übertragendem Byte 16 Prozessortakte zur Verfügung, von den allerdings die meisten als Overhead (springen in und aus der ISR) wieder wegfallen. Das mit dem zweiten Controller habe ich mir auch schon überlegt, versuche ich aber zu vermeiden, weil dadurch eine Menge zusätzlicher Komplexität entsteht. Werde mir mal sd_raw_read_interval() genauer angucken. Danke für die Tips, Thorsten
Datum:
Thorsten Die FAT-Routinen kannst Du nicht in eine ISR packen weil die einfach zu lange dauern. Nach kurzer Zeit gibt es einen Stack-Überlauf. Die einzige Lösung wäre ein FIFO-Buffer der in einer ISR gefüllt wird. Wenn Du Daten vom TWI lesen willst dann hast Du doch schon fast gewonnen. Dafür gibt es doch extra eine ISR. In der Hauptschleife schaust Du einfach ständig nach ob der FIFO neue Daten enthält und schreibst diese weg. Torsten
Datum:
Hallo, > Da meine Datenrate recht konstant ist, bringt ein > grösserer Datenpuffer nicht so richtig was (wenn die > Daten schneller kommen, als der Prozessor sie > wegschreiben kann, geht es halt einfach nicht, > egal wie gross der Puffer ist). Wenn die Daten mit 20kB/s kommen und Du 60kB/s wegschreiben kannst, kommen sie doch nicht schneller als Du sie schreiben kannst?!? Ich denke, hier kommt es entscheidend darauf an, wie die Sample-Daten zustande kommen. Vorausgesetzt, die Daten werden durch den AVR parallel ohne Zutun des Programms erzeugt (z.B. im ADC), kann man es wie folgt machen: 1. Man reserviert sich zwei oder mehr Puffer, von denen immer genau einer "aktiv" ist. 2. Sind neue Daten verfügbar, wird ein Interrupt ausgelöst, in dessen ISR man die neuen Daten in den aktiven Puffer schreibt. Ist der Puffer voll, wird der andere Puffer aktiv und empfängt ab dann neue Daten. 3. In der Hauptschleife wird überprüft, ob es einen vollen Puffer gibt. Wenn ja wird dieser auf die Karte geschrieben und anschließend geleert. Statt mehreren Puffern könnte man je nach Datenrate auch einen einzelnen als Ringpuffer nehmen und zu schreiben beginnen, wenn mehr als 512 Byte enthalten sind. Natürlich muss das Timing bzw. die Datenrate so passen, dass in der Zeit, in der der eine Puffer auf die Karte geschrieben wird, der andere nicht überläuft. Werden die Daten nicht über einen Interrupt angekündigt, kann man die Warteschleife in sd_raw_write() vielleicht dennoch durch einen Timer-Interrupt unterbrechen, der dann weitere Datensamples zwischenspeichert. Gruß, Roland
Datum:
Torsten, Ich dachte auch nicht dran, die FAT16-Routinen samt ihren Wartezyklen in eine ISR zu packen, sondern die SPI-ISR so zu schreiben, dass sie bei jedem Aufruf entscheidet, was als nächstes zu tun ist (Byte zum SPI schreiben/lesen, wenn der Block fertig ist, gucken was als nächstes zu tun ist, z.B. die FAT Einträge draus lesen usw.). Würde aber trotzdem eine ziemlich grosse ISR geben, auch wenn bei jedem Aufruf nur ein kleiner Teil davon zur Ausführung kommt. Das ist auch meiner Meinung nach nicht der richtige Weg. Das Problem ist halt, dass viele der Routinen einfach "busy" warten, bis der Kartenzugriff abgeschlossen ist. Dadurch kriege ich immer die Latenzen, egal ob die Karte nun durch eine ISR oder eine andere Routine angesteuert wird. Was möglicherweise ginge, wäre aber der umgekehrte Weg: - Es gibt nicht einen Buffer, sondern zwei. Ein Pointer zeigt auf den gerade aktiven. - Wenn ein Block geschrieben werden soll, wird der SPI Interrupt aktiviert und das erste Byte geschrieben. Die ISR sorgt dann dafür, dass der Buffer asynchron auf die Karte geschrieben wird (Globale Statusvariablen kontrollieren das, wenn der Block fertig ist, deaktiviert die ISR den SPI Interrupt). Gleichzeitig wird der Zeiger auf den zweiten Buffer gestellt, so dass weitere Schreibzugriffe abgebuffert werden können. Die sd_raw Funktion kann sofort zurückkehren. Wo ich noch nicht so genau weiss, wie man es lösen könnte, ist das lesen: Was mache ich mit einer Routine, die einen Block einliest und dann bearbeitet? Die blockiert dann wieder... (zwangsläufig). Was hältst Du davon? Die andere Möglichkeit wäre, wie Du schreibst, die TWI ISR zu benutzen. Ich muss mir nur noch überlegen, wie ich die Messung antriggere, könnte ich in meiner RTC ISR am INT0 machen (die kriegt 32768Hz von der RTC). Ansonsten wäre das evtl. noch besser, denn die TWI ISR feuert nicht so schnell wie die SPI ISR (400kHz vs. 7MHz), d.h. mir bleiben mehr Takte dazwischen übrig. Mal gucken... Gruss, Thorsten
Datum:
Roland, > Wenn die Daten mit 20kB/s kommen und Du 60kB/s wegschreiben kannst, > kommen sie doch nicht schneller als Du sie schreiben kannst?!? Sorry, hab mich wohl undeutlich ausgedrückt. Der grössere Datenpuffer bringt mir natürlich deswegen nix, weil ich Samples verpasse, während ich auf die Karte warte (und daher nicht messen & in den Buffer schreiben kann). Er würde aber auch bei zu hohen Datenraten nix bringen (das wollte ich eigentlich zum Ausdruck bringen). Mein Problem sind aber, wie gesagt, die Latenzen. Ich glaube inzwischen, dass es am besten ist, zu versuchen die Messungen komplett über die ISRs zu steuern, während der Kartenzugriff dann vom Hauptprogramm aus kontrolliert wird. Werde mal Versuche machen und berichten, wie es so klappt. Gruss, Thorsten
Datum:
> - Es gibt nicht einen Buffer, sondern zwei. Ein Pointer zeigt auf den > gerade aktiven. Double Buffering eben, geht auch. Nur, der Mega hat wenig Speicher und der Verwaltungsaufwand dafür ist auch erheblich. Viel einfacher wäre es mit einem Ring-Buffer und Zeigern auf Head und Tail zu arbeiten. > - Wenn ein Block geschrieben werden soll, wird der SPI Interrupt > aktiviert und das erste Byte geschrieben. Die ISR sorgt dann dafür, > dass der Buffer asynchron auf die Karte geschrieben wird (Globale > Statusvariablen kontrollieren das, wenn der Block fertig ist, > deaktiviert die ISR den SPI Interrupt). Gleichzeitig wird der Zeiger > auf den zweiten Buffer gestellt, so dass weitere Schreibzugriffe > abgebuffert werden können. Die sd_raw Funktion kann sofort > zurückkehren. Das mit dem SPI Interrupt hört sich gut an. Leider muß dann Roland's Code komplett neu geschrieben werden. ;) > Wo ich noch nicht so genau weiss, wie man es lösen könnte, ist das > lesen: Was mache ich mit einer Routine, die einen Block einliest und > dann bearbeitet? Die blockiert dann wieder... (zwangsläufig). Ja, das stimmt. Schwierig zu lösen. > Was hältst Du davon? Google mal nach einem Projekt nennt sich "AVRCam". Das Konzept gefällt mir sehr gut. Dort wird mit einer globalen Event-FIFO gearbeitet. Fast alle Events sind nicht-blockierend. TWI wurde auch komplett in die ISR ausgelagert. Schau Dir die Quelltexte unbedingt einmal an. Wenn dieses Projekt CPU- und Speicher-intensives Video verarbeiten kann muß es doch möglich sein einen Datenlogger mit SD-Karte auf die Beine zu stellen. ;-) BTW: Die disk-info von Malte nach einer Neuformatierung >free: 120578048/254795776 gefällt mir überhaupt nicht. So ähnlich verhielt sich auch meine Karte auch kurz bevor sie ganz und gar den Geist aufgegeben hat. :-( Torsten
Datum:
Hallo Thorsten, Ich glaube, wir missverstehen uns hier ein bisschen. Wovon ich oben ausgegangen bin ist, dass die Messung als solche durch eine Hardware-Einheit des AVR stattfindet, somit keine MCU-Zeit braucht und zum Schluss jeder Messung ein Interrupt (wie der des ADC) auslöst. Die Interrupts sind doch in der Hinsicht praktisch, dass sie eben das busy waiting unterbrechen. D.h. zeitkritische Sachen (wie das Erfassen eines Messwertes) erledigt man in einer ISR, und Arbeiten mit "hohen Latenzen" (wie das Schreiben auf die Karte) erledigt man im Hauptprogramm. Dem SPI bzw. der Karte ist es ja wurscht, ob durch die ISR-Abarbeitung eine kleine Verzögerung im Datenverkehr auftritt. Der Interrupt, der am Ende der Messung ausgelöst wird, garantiert, dass man den Messwert nicht verpasst. Das alles funktioniert natürlich nicht, wenn das Messen als solches keine Interrupts auslöst und noch dazu MCU-Zeit verbraucht. Was misst Du denn, und wie genau? Irgendetwas mit dem SPI-Interrupt anzufangen halte ich für sinnlos. Der feuert mit knapp 1MHz zu häufig. Natürlich muss das mit den Puffergrößen und den Verzögerungszeiten durch das Wegschreiben zusammenpassen. Aber irgendwann sind halt die Grenzen der MCU erreicht, was Verarbeitungsgeschwindigkeit und Speichergrößen betrifft. Eventuell sollte man dann einen anderen Controller wählen. Roland
Datum:
Vielleicht mit weniger Worten in Pseudocode:
ISR(ADC_complete)
{
puffer.add(ADC_value);
}
int main()
{
while(true)
{
if(puffer.size >= 512)
{
sd_raw_write(puffer.data(0 to 511));
puffer.remove(0 to 511);
}
}
}
Natürlich wäre der Zugriff auf den Puffer noch mit einer Semaphore oder
ähnlichem zu synchronisieren.
Roland
Datum:
> Ich glaube, wir missverstehen uns hier ein bisschen. Wovon ich oben > ausgegangen bin ist, dass die Messung als solche durch eine > Hardware-Einheit des AVR stattfindet, somit keine MCU-Zeit braucht und > zum Schluss jeder Messung ein Interrupt (wie der des ADC) auslöst. Ich bin zwar der Torsten ohne 'h' im Namen aber der andere wollte Daten vom TWI mit Hilfe eines MAX127 (kenne ich nicht...) lesen. Also mit HW Unterstützung, und hoffentlich ohne busy-wait beim Register lesen. > Irgendetwas mit dem SPI-Interrupt anzufangen halte ich für sinnlos. Der > feuert mit knapp 1MHz zu häufig. Ops, Du hast recht. Eine ISR macht bei der Geschwindigkeit keinen Sinn mehr. Torsten
Datum:
Oops, habe gerade gemerkt dass da während dem Schreiben meiner beiden Beiträge noch was dazugekommen ist. Ich meinte also nicht Dich, Thorsten S., sondern den anderen Thorsten :) Roland
Datum:
@Torsten (ohne h) Das mit dem TWI hatte ich überlesen. D.h. für das Messen ist auch ein Polling nötig. Dann wird das natürlich schwieriger, ohje...
Datum:
Hallo Roland, Also ich mach das genau so wie deinem Pseudocode. Das Problem ist nur, dass während sd_raw_write schon wieder neue Interrupts kommen. Wozu eigentlich das busy waiting? Wenn man den SPI nicht anderweitg verwendet, kann man die Karte doch in Ruhe schreiben lassen, während man den nächsten Puffer mit Daten vollmacht, ohne erst zu warten bis die Karte fertig ist. Das ist auf jeden Fall genug Zeit. Man kann dann ja VOR dem nächsten Schreiben das busy flag prüfen. Siehe http://elm-chan.org/docs/mmc/mmc_e.html Die von mir berichteten langen Schreibzeiten nach 4096 byte kommen übrigens von einem karteninternen Puffer (dito). Malte
Datum:
Roland, ich sehe, worauf Du hinauswillst. Gemessen wird mit zwei MAX127 am I2C Bus. Für jeden Messwert müssen 5 bytes über den Bus (Adresse + Kontrollbyte zum starten der Messung, dann Adresse plus zwei Nullbytes zum lesen des Messwertes). Pro Messung (16 Kanäle) sind das also 80 bytes, bei 400kHz also ca. 1.6ms. Bei einem Sample-Interval von 4ms hätte ich dann noch ca. 2.4ms pro Takt zum speichern, was zwar im Mittel ausreicht, wegen dem angesprochenen Latenzproblem jedoch nicht funktioniert. Zur ISR: Bisher verwende ich eine modifizierte Variante des Atmel-Beispielcodes. Die ISR kümmert sich hier ums versenden/empfangen der Messages, initialisieren und verarbeiten tu ich die Ergebnisse in einer normalen Unterfunktion, die im Augenblick noch vom Hauptprogramm aus aufgerufen wird. Das Timing geschieht in einer ISR, die von einem 32kHz Takt angesteuert wird (der Takt kommt von der RTC). Wenn ich nun aus dieser ISR jeweils alle 4ms die erste TWI Message anschubse, und in der TWI-ISR dann (gesteuert über ein globales Flag) automatisch die nächste TWI Message vorbereite, wenn die letzte vollständig ist (usw.), könnte es gehen. Die Messwerte in der TWI-ISR in einen Buffer schreiben, der einfach im Hauptprogramm dann gemütlich auf die SD-Karte wandert. So könnte es gehen. Und das beste: Ich muss den SD-Code nicht verändern. Dafür halt die TWI-ISR. Werde das mal so probieren. @Torsten: Werde mir auch mal AVRCam angucken, danke für den Tip. Das Forum hier ist spitze :-) Gruss, Thorsten
Datum:
Hallo Malte, Es macht doch nichts, wenn die Karte noch schreibt und schon der nächste Interrupt kommt? Wenn Du, wie oben beschrieben, zwei Puffer abwechselnd füllst und gleichzeitig den jeweils anderen schreibst, kommt Dir das ja nicht in die Quere. In meinem Pseudocode oben war puffer als Ringpuffer gedacht. D.h. Du kannst vorne Daten entnehmen, um sie auf die Karte zu schreiben, und gleichzeitig hinten neue Daten im Interrupt anhängen. Das dürfte bei Dir auch besser funktionieren als bei Thorsten, der eine wesentlich höhere Datenrate zu bewältigen hat. Das Verschieben der Wartezyklen an den Anfang könnte funktionieren. Müsste man mal ausprobieren. Wie schon erwähnt weiß ich nicht, ob die Karte den SPI-Takt, der durch das Polling erzeugt wird, zum Schreiben benötigt. Wenn das der Fall ist bringt das verschieben des Wartezyklus nichts. Roland
Datum:
> Das mit dem TWI hatte ich überlesen. D.h. für das Messen ist auch ein > Polling nötig. Dann wird das natürlich schwieriger, ohje... Nein, ganz im Gegenteil, das macht es ja einfacher weil es eine extra ISR für TWI gibt. Mein Problem ist dass ich den MAX127 noch nicht kenne und die Art und Weise wie man an dessen Daten kommt. Ich google gleich mal. Langsam wird der Thread unübersichtlich, mehr als 100 Beiträge. Scrollen macht jetzt keinen Spaß mehr. Was haltet Ihr von einer Fortsetzung in einem neuen Thread? Torsten
Datum:
Ich meinte, schwieriger im Sinne meines Lösungsvorschlages. Der funktioniert dann nicht mehr. Einen neuen Thread fände ich gut, aber nur für die Probleme von Malte und Thorsten. Antworten auf Fragen direkt zu meinem Code oder neue Versionen von diesem werde ich wohl weiterhin hierher posten. Roland
Datum:
Hallo Roland, >Es macht doch nichts, wenn die Karte noch schreibt und schon der >nächste Interrupt kommt? Irgendwie scheinbar doch. Es fehlen immer Samples. Allerdings arbeite ich mit nur einem Puffer, weil ich denke, dass das Wegschreiben über SPI wesentlich schneller geht als das Einlaufen neuer Samples. Das muss ich mir aber noch mal genau überlegen, vielleicht liegt da der Hase im Pfeffer. >Wie schon erwähnt weiß ich nicht, ob die >Karte den SPI-Takt, der durch das Polling erzeugt wird, zum Schreiben >benötigt. In dem von mir oben zitierten Link steht folgendes: "In principle of the SPI mode, the CS signal must be asserted during a transaction, however there is an exception to this rule. When the card is busy, the host controller can deassert CS to release SPI bus for any other SPI devices. The card will drive DO signal low again when reselect it during internal process is in progress. Therefore a preceding busy check (wait ready immediataly before command and data packet) instead of post wait can eliminate waste wait time." Daraus schliesse ich, dass das Polling nicht benötigt wird. In dem Link steht übrigens noch so einiges über write-performance Verbesserung, zB. dass MMCs viel schneller sind als SDs... Gruß Malte
Datum:
Hallo, das Verschieben der Wartezyklen an den Anfang hat bei mir nicht funktioniert. Nach ein paar Schreibzyklen stürzt irgendwas ab. Dafür funktioniert jetzt bei mir alles, nachdem ich einen zweiten Puffer eingeführt habe. Wenn der erste voll ist wird er per memcpy in den zweiten kopiert und der zweite dann weggeschrieben. Kann man sicher noch eleganter machen... Allerdings kann ich jetzt nur noch mit 256 bytes Puffergröße arbeiten. Bei 512 sagt der Compiler zwar, dass nur ~95% des Speichers voll sind, das Programm läuft aber trotzdem nicht mehr. Da muss ich nochmal ein bisschen im Forum suchen um zu verstehen, woran das liegt. Gruß Malte
Datum:
Hallo Malte, Danke für das Zitat der Seite. Den Link kannte ich zwar schon, die Stelle über das Vorziehen der Wartezeit hatte ich jedoch auf die Schnelle nicht gefunden. Wenn ich dazu komme werde ich das mit dem Vorziehen selbst mal ausprobieren. Mal sehen ob ich da was zustande bringe. Das memcpy() kannst Du Dir sparen, wenn Du einen Pointer auf den Pufferanfang zum Schreiben verwendest. Dann brauchst Du dem Pointer für den Pufferwechsel nur die Adresse des anderen Puffers zuweisen und schon ist dieser aktiv. Wenn es mit 2x512 Bytes nicht mehr funktioniert, liegt das wahrscheinlich daran, dass der Stack in den Heap reinwächst. Kurz, Dir geht das RAM aus. Denn zu den 2x512Byte kommen ja noch die 512Byte Schreib-/Lesepuffer innerhalb von sd_raw hinzu. Dann bleiben von den 2kB des ATmega32 für alle Variablen, den Stack und den Heap nur noch 512Bytes übrig, und das wird wohl zu wenig sein. Gruß, Roland
Datum:
Hi! >Wie schon erwähnt weiß ich nicht, ob die >Karte den SPI-Takt, der durch das Polling erzeugt wird, zum Schreiben >benötigt. Habe in der Hinsicht mal Messungen gemacht und festgestellt das langsame Karten dadurch viel schneller schreiben 1,8/1,1ms @250KHz/1MHz. Bei Karten, die von sich aus schon recht schnell sind, ist der Unterschied deutlich geringer 393us/372us. Wenn der Takt also ganz wegbleibt kann das schon zu Zeitverlust führen. Die gemessene Zeit ist übrigens der Abstand zwischen dem Ende des letzten zu schreibenden Byte und der Busy-reaktion, also reine Schreibzeit. Viel Erfolg, Uwe
Datum:
Hallo, ich habe mal wieder ein Problem: das Vergrößern von files mit fat16_resize_file() funktioniert problemlos. Ein Verkleinern führt aber dazu, daß zumindest Windows das File zwar anzeigt aber nicht mehr öffnen kann. Eine Reparatur über "Fehlerüberprüfung" ist möglich, wenngleich etwas nervig. Ich benötige das Verkleinern aus folgendem Grund: Zunächst gehe ich davon aus, dass ich einen gesamten "Tagesfile" von etw 5MB aufnehmen werde und blähe die neue Datei auf diese Größe auf, um die vielen FAT Zugriffe zu vermeiden. Falls die Datenaufnahme aber vorher unterbrochen wird, möchte ich den File auf die entsprechende Länge zusammenstutzen. Der Ablauf ist etwa so: fat16_create_file(...) open_file_in_dir(...) fat16_resize_file (fd, 5000000) fat16_write_file(...) ... ... fat16_resize_file (fd, new_size) fat16_close_file (fd) sd_raw_sync() Wenn new_size >=5M ist geht es, sonst nicht. Woran könnte das liegen? Gruß Malte
Datum:
Hallo Malte, Danke für den Hinweis. Aufgrund Deiner Probleme habe ich mir die Funktion fat16_resize_file() nochmal genauer angeschaut und festgestellt, dass diese seit der Version 20060808 zwei gravierende Fehler enthält. Durch diese wird u.a. beim Verkleinern einer Datei deren Clusterkette, die den Dateiinhalt enthält, in der FAT nicht richtig abgeschlossen. Das dürfte auch der Grund sein, warum Windows meckert. Ich werde hier morgen eine korrigierte Version posten. Gruß, Roland
Datum:
Angehängte Dateien:@Malte In der angehängten fat16.c habe ich die folgenden Fehler korrigiert: - Verkleinerte Dateien werden korrekt abgeschlossen. - Abhängig von der Kartengröße wird der freie Speicherplatz nicht richtig berechnet, wenn die FAT-Größe UINT16_MAX übersteigt. Könntest Du die Datei bei Dir bitte kurz antesten? Nach Deinem Ok würde ich dann ein neues Quellcode-Paket erstellen. Danke und Gruß, Roland
Datum:
Angehängte Dateien:Schande über mich! Die eben gepostete Version funktioniert nicht, wenn leere Dateien auf eine Größe kleiner der Clustergröße vergrößert werden. Die angehängte Version tut jetzt aber hoffentlich. Roland
Datum:
Hallo Roland, vielen Dank für die überarbeitete Version. Das Verkleinern von Dateien klappt jetzt bei meinen Tests! Die Anzeige des freien Speicherplatzes stimmt nicht ganz: > ls 1455 MAIN.C 19200 malte.dat > disk manuf: 0x02 oem: TM prod: SD256 rev: 68 serial: 0x707dd547 date: 03/05 size: 255066112 copy: 0 wr.pr.: 0/0 format: 0 free: 240644096/254795776 H:\>dir Datenträger in Laufwerk H: hat keine Bezeichnung. Datenträgernummer: 44F0-263B Verzeichnis von H:\ 12.09.2005 23:54 1,455 main.c 01.01.1601 02:00 19,200 malte.dat 2 Datei(en) 20,655 Bytes 0 Verzeichnis(se), 254,275,584 Bytes frei Mir würde es aber auch reichen, wenn der return value von fat16_write_file() korrekt arbeitet, also '0 on disk full'. Ich habe das noch nicht ausprobiert. Es geht nur darum, während des Betriebes festzustellen, ob die Karte schon voll ist. Gruß Malte
Datum:
Hallo Malte, Danke für den Test. Mit Deinem FAT-Image habe ich das Problem mit der nicht ganz korrekten Anzeige des freien Speicherplatzes auch, kann es mir aber nicht erklären. Vielleicht hilft es, wenn Du unter Linux nochmal mit mkdosfs -F 16 /dev/sda1 formatierst. Eventuell gibt es da durch vorangegangene Tests noch kleine Inkonsistenzen. Roland
Datum:
Angehängte Dateien:Mal wieder gibts ein neues Source-Package auf meiner Homepage und auch angehängt an dieses Posting. Korrigiert habe ich wie schon diskutiert das Verkleinern von Dateien und die Berechnung des freien Speicherplatzes. @Malte Könntest Du bitte auf diese neue Version aktualisieren? Jetzt funktioniert die Speicherplatzberechnung auch mit Deiner FAT. Ich sollte Code-Änderungen einfach nicht voreilig posten... Gute Nacht, Roland
Datum:
Hallo Roland, die Anzeige des freien Speichers nähert asymptotisch dem unter Windows angezeigten. Ich bekomme jetzt (nach einem mkdosfs -F 16 /dev/sda1): 254 369 799 (SD-reader) 254 435 328 (Win) Die Gesamtgröße der Karte wird bei beiden gleich angezeigt. Unter Windows wird allerdings, auch wenn sich nur ein 10 byte große Datei auf der Karte befindet, 4096 Byte belegter Speicher angezeigt. Ich weiss nicht, ob man der Sache auf den Grund gehen muß. Besten Dank und Gruß Malte
Datum:
Hi Malte, Na das sieht ja schon ganz gut aus. Die 16 Cluster Unterschied machen nichts aus, das wird an einer im Detail unterschiedlichen Zählweise liegen. Ein bisschen wundern tut mich bloß, dass der AVR eine ungerade Bytezahl ausspuckt (oder ist das bloß ein Tippfehler?). Das mit der 10 Bytes großen Datei sollte mit meinem Code aber genauso sein, schließlich belegt sie einen ganzen Cluster von eben genau 4kB Größe. Und die Berechnung des freien Speicherplatzes beruht ja auf der Anzahl komplett freier Cluster. Viele Grüße, Roland
Datum:
Hallo Roland,
ich habe ein Problem mit der Funktion fat16_write_file,
/* calculate new file position */
buffer += write_length;
buffer_left -= write_length;
fd->pos += write_length;
Ist die zu schreibende Datei, die einzige Datei auf dem Datenträger
wird der Dir. Eintrag nicht neu geschrieben. In der Abfrage sind dann
beide Werte gleich:
/* update directory entry */
if(fd->pos > fd->dir_entry.file_size)
Wenn eine 2. Datei da ist, wird ein Update des Dir. aufgerufen.
Funktioniert jedoch nicht. Im Dir. Eintrag steht dann noch die Alte
Größe wobei die Dateidaten abgelegt wurden.
Viele Grüße
Reinhold
Datum:
Hallo Reinhold, Könntest Du das bitte ein bisschen näher erläutern, was genau Dein Problem ist? Was hat insbesondere das von Dir zitierte if-Statement mit der Anzahl der gespeicherten Dateien zu tun? Kannst Du einen Korrekturvorschlag machen? Vielleicht verstehe ich dann besser, was Du meinst. Roland
Datum:
Hallo Roland,
das Problem hat sich geklärt. Die Funktion "sd_raw_sync()" wurde
nicht angesprochen deshalb wurde das Dir. nicht upgedatet. Ein
Speicherproblem war die 2. Ursache.
Wenn ich allerdings an eine Datei ohne Offset Daten anhängen will hab
ich ein Problem.
Die Ursache liegt in der Funktion:
fat16_seek_file(fd,&offset , FAT16_SEEK_END);
Ist offset = 0 wird diese mit return 0 abgebrochen.
Mein Vorschlag:
uint8_t fat16_seek_file(struct fat16_file_struct* fd, int32_t* offset,
uint8_t whence)
{
if(!fd ) // || !offset
return 0;
uint32_t new_pos = fd->pos;
switch(whence)
{
case FAT16_SEEK_SET:
new_pos = *offset;
break;
case FAT16_SEEK_CUR:
new_pos += *offset;
break;
case FAT16_SEEK_END:
new_pos = fd->dir_entry.file_size + *offset;
break;
default:
return 0;
}
if(new_pos > fd->dir_entry.file_size && !fat16_resize_file(fd,
new_pos))
return 0;
fd->pos = new_pos;
fd->pos_cluster = 0;
*offset = new_pos;
return 1;
}
Oder mache ich was falsch?
Gruß und Danke schon mal für den Code
Reinhold
Datum:
Hallo Reinhold! Ja, Du machst etwas falsch, aber Du bist nicht der erste... Bitte schau Dir die Funktionsdeklaration nochmal genau an. Der Parameter offset ist vom Typ uint32_t* (man achte auf den Stern). Übergebe einen Zeiger auf eine Variable mit dem Inhalt 0, dann funktioniert es. Die Funktion nutzt den Zeiger, um Dir den absoluten Offset zurückzugeben, falls Du ihr nur einen relativen Offset gegeben hast. Gruß, Roland
Datum:
Hallo Roland, jau ich hab meinen Fehler erkannt.... Gibt es einen Beispielcode zum anlegen eines Unterverzeichnisses? Ich muss mit Unterverzeichnissen arbeiten da im Rootverzeichnis die Anzahl der Einträge ja begrenzt ist. Bei einer neu formatierten SD soll dann das Verzeichnis automatisch angelegt werden. Gruß Reinhold
Datum:
Hallo Reinhold, Am einfachsten wäre es natürlich, den Ordner am PC zu erstellen. Ansonsten könntest Du fat16_create_file() leicht abwandeln. Ein Ordner ist bei FAT16 nichts anderes als eine Datei mit den Verzeichniseinträgen als Inhalt. Wenn Du der Datei das Flag FAT16_ATTRIB_DIR gibst, wird sie zum Ordner. Eine Funktion gibt es dafür im Moment nicht. Roland
Datum:
Hat das jemand schon einmal mit einer Kingston 256MB SD-Karte
hinbekommen ?
Ich bekomme bei dem Card init in Zeile 212 von sd_raw.c einen "test2"
Fehler:
/* reset card */
uint8_t response;
for(uint16_t i = 0; ; ++i)
{
response = sd_raw_send_command_r1(CMD_GO_IDLE_STATE, 0);
if(response == (1 << R1_IDLE_STATE))
{ printf("test1\n");
break;
}
if(i == 0x1ff)
{
unselect_card();
printf("test2\n");
return 0;
}
}
Die Karte läuft mit 3,3V über Spannungsregler. Teiler sind 3K3 und 2K
Ohm, d.h. bei der Karte kommen die Pegel mit etwas über 3 Volt an.
Nun ja, nicht so optimal.
Würde auch 10k mit 6,6k gehen ? Dann liegt allerdings I=0,5mA recht
niedrig ...
Datum:
So, geht jetzt, war ein elektrischer Fehler. Vielen Dank für die Library !!! Jetzt steht dem Abenteuer SD-Card nichts mehr im Wege :-) Für den 644er musste ich Änderungen am Interface machen. Die Register enden dort alle mit "0" (z.B. SPCR0). Pete
Datum:
Hallo Pete, Mit meiner Vermutung, dass etwas mit der SPI-Beschaltung nicht stimmt, bin ich jetzt wohl zu spät dran... Aber gut, dass es jetzt läuft. An was lag es denn genau? Das mit den unterschiedlichen Registernamen ist ein leidiges Thema. Es wird sich nicht vermeiden lassen, hier und dort einige Anpassungen an die jeweils verwendete MCU vorzunehmen. Einige gängige mega-Typen unterstütze ich ja von Haus aus, für exotischere AVRs will ich den Code aber nicht unnötig "ver-#ifdef-en", das wird dadurch eh alles schon nicht schöner. Gruß, Roland
Datum:
Hallo Roland,
die Funktion fat16_create_file() habe ich modifiziert zu
fat16_create_dir(). Das Ende der Funktion habe ich dazu modifiziert.
Der Dir-Eintrag im Root-Dir wird auch geschrieben aber das
Unterverzeichnis funktioniert nicht richtig.
.......
cluster_num= fat16_append_clusters(fs, 0, 1);
/* write directory entry to disk */
dir_entry->cluster=cluster_num;
dir_entry->attributes=FAT16_ATTRIB_DIR;
dir_entry->date_create=format_time();
dir_entry->date_change=format_time();
dir_entry->entry_offset = dir_entry_offset;
if(!fat16_write_dir_entry(fs, dir_entry))
return 0;
return 1;
#else
return 0;
#endif
}
Ach ja das dir_entry habe ich um die Zeit/Datumsinformation erweitert.
Was muß ich machen damit das Unterverzeichnis richtig arbeitet?
Gruß
Reinhold
Datum:
Hallo Roland, ich hab herausgefunden das die SUBs nur dann nicht funktionieren wenn in dem entsprechenden Cluster noch Datenmüll von gelöschten Dateien steht. Bei einer gereinigten frisch formatierten SD geht alles! Also muss ich jetzt nur noch den entsprechenden Cluster in dem das Verzeichnis sein soll vorher löschen oder? Gruß Reinhold
Datum:
Hallo Reinhold, Ja, dass Nullen der neu allokierten Verzeichniscluster ist ok. Es reicht aus, wenn Du jedes 32. Byte (bei Offset 0 gestartet) auf 0 oder FAT16_DIRENTRY_DELETED setzt. Ich habe mich bisher darum gedrückt, da es ja doch einiges an Overhead darstellt. Siehe dazu den TODO-Kommentar in fat16_create_file(). Effizienter und ohne z.B. 128 einzelne Schreibzugriffe (bei Clustern von 4kB), die die Lebensdauer der Karte beinträchtigen, lässt sich das mit einer Callback-Technik a la sd_raw_read_interval() machen. Du solltest auch in jedem Unterverzeichnis zwei weitere Unterverzeichnisse mit den Namen "." und ".." anlegen, die auf das aktuelle Verzeichnis bzw. das Verzeichnis darüber verweisen. Erst dann ist eine korrekte Ordnernavigation gewährleistet. Roland
Datum:
Mist, ich habe möglicherweise schon wieder eine Karte geschrottet. :( Folgendes ist mir passiert: Ich nutze Roland's Code um in einem Datenlogger alle 15min Temperaturwerte von DS18S20 Sensoren aufzuzeichnen. Nur ein paar chars, immer in die gleiche Datei. Nichts zeitkritisches, funktioniert super. Den 'sync' Befehl nach dem schreiben hab ich auch nicht vergessen. Nun dachte ich mir, es ist mal Zeit für einen Langzeit-Test und habe meiner Schaltung die auf einem Steckbrett aufgebaut ist einen Akku spendiert und in die Ecke gestellt. Und natürlich vergessen. Irgendwann habe ich mich wieder erinnert und nachgesehen. Klar war der Akku leer. Ok, Karte entfernt und in den Cardreader am PC gesteckt. Nun der große Schreck - XP meint: Der Datenträger ist nicht formatiert. Weder unter Linux noch unter XP mit dem SD-Formatter von Panasonic konnte ich die Karte wieder zum Leben erwecken. Fehlermeldung: write-protected. Gut, eine neue kostet kein Vermögen. Aber die alte Karte kann sich doch nicht einfach in Sonder-Müll verwandeln wenn die Stromversorgung mal einknickt. Hat jemand zufälligerweise ähnliche Probleme gehabt oder eine Idee ob man evtl. mit einem Raw-Write an bestimmter Stelle die Karte(n) retten könnte? Torsten
Datum:
Ergänzung: Unter Ubuntu (Linux) sehe ich die Karte und kann auch Files lesen. Formatieren geht auch nicht. Weder mit mkdosfs noch mit cat /dev/zero </dev/speicherkarte>. Haben wir uns ausgesperrt ?? P.S.: T.S.: Könntest Du Deinen Code vielleicht hier posten ?
Datum:
> Ich habe die gleichen Probleme :-( Wie ist es bei Dir passiert? > Haben wir uns ausgesperrt ?? Ich glaube schon. Auch weil es nicht meine erste Karte ist. Irgend etwas ist oberfaul. Mag sein wegen der sehr lückenhaften Doku. > Könntest Du Deinen Code vielleicht hier posten ? Hhmm. Das macht atm nicht wirklich Sinn weil ich bestimmt andere HW verwende und gerade erst angefangen habe. Mitten drin beim experimentieren so zu sagen - und noch lange nicht fertig. Wenn Du aber unbedingt darauf bestehst bekommst Du selbstverständlich den Quelltext. Ich brauche dann aber Deine Mail Adresse und Dein Einverständnis das Roland ein Cc bekommt. Torsten
Datum:
Hallo T.S., meine email Adresse ist p e t e r - k r u s e (a t) g m x. n e t. Gerne mit Kopie an Roland. Ich vermute, dass beim Schreiben etwas daneben gegangen ist.(?) Gruss, Pete
Datum:
@Pete Done. @AVR Nix Zwar kenne ich den thread schon, weil aber auch dieser so ellenlang ist, ist mir genau das entgangen. Danke für den Link. :-) Torsten
Datum:
Habe aber auch in dem Thread keine Lösung für die "Read-only"-Karten gefunden...
Datum:
Hallo, habt ihr eigentlich schon mal überlegt, wie man solch eine Fehlfunktion durch Stromausfall verhindern könnte? Würde mich sehr interessieren, denn sowas kann ja bei jedem autark arbeitenden Datenlogger passieren. Bei meinem System habe ich mich noch nicht getraut, den Stecker während des Schreibens zu ziehen. Kann man da vielleicht mit dem Brown Out Detector was machen? (Ich habe mich noch nicht damit beschäftigt) Gruß Malte
Datum:
Nun ja, irgendwann möchte ich die Daten auch auf meinen PC übertragen. Ich werde vor dem Schreibvorgang eine LED anmachen und nach dem Schreiben wieder aus. Dann kann ich sehen, wann ich ziehen darf.
Datum:
Hallo Ihr Kartentöter, Mal ne blöde Frage, Wie sieht denn euer CSD-Reg. an Bitpos.13-15 und 84-95 aus? Schreibschutz? Card Command Classes? Ich würde da jetzt mal anfangen zu suchen. MFG Uwe
Datum:
@Malte
Nachgedacht schon, aber noch keine Lösung gefunden. Der Brown Out
Detector nützt in meinem Fall gar nichts, weil auch bei fast entladenem
Akku die Zellspannung locker ausreicht. Nur bei hoher Belastung während
eines Schreibvorganges auf die Karte knickt die Spannung ein. Dann,
wenn es zu spät ist.
@Pete
Ich habe die Empfehlung in dem o.g. Thread mal angepasst &
ausprobiert:
if(sd_raw_send_command_r1(CMD_CLR_WRITE_PROT, 0))
{
unselect_card();
return 0;
}
Geht nicht wie zu erwarten war. Vielleicht muß die '0' durch etwas
anderes ersetzt werden. Bin ratlos.
Torsten
Datum:
@Torsten: Hast Du Deine Karte wieder reaktieren können ? Beantwortet ist auch noch nicht Deine Frage nach der Reaktivierung der Karte ...
Datum:
Hallo hatte leider noch keine Zeit mich in den Source einzuarbeiten. Arbeite aber mit einer selbstgeschriebenen Software Aber einige Fragen bzw. Anmerkungen hätte ich schon. Wie stellt das Programm die relative Adresse der FAT Sektoren fest? Meiner Erfahrung nach liegt nähmlich der erste Sektor des Dateisystemes je nach Kartengrösse nicht ab der Adresse 0x00000000 sondern etwa bei einer 32 MB Karte erst bei 0x00006600. Obwohl er etwa in WINHEX bei 0x00000000 auftaucht.(Im Moment gehe ich nicht von einem Fehler meiner Software aus) Jetzt meine Frage könnte das mit dem Writeprotect-Managment der SD Karte zusammenhängen. Und was passiert wenn man in diese Sektoren Daten reinschreibt. Eine weitere Frage wäre weiss irgentjemand hier wo ich eine genaue Dokumentation über das WriteProtectmanagment herbekomme. In den Üblichen Datenblättern etwa von Sandisk steht dazu nämlich leider nicht viel drin.
Datum:
Hallo, lässt sich der Code dahingehend einstellen, dass ich mittels ATmega8 schreibend auf das FAT16 - Dateiformat zugreifen kann? Welche Einstellungen müssen hierfür getätigt werden? Unter BASCOM mittels DOS-AVR bekommt man das nicht realisiert, weil hierfür einfach nicht genügend RAM zur Verfügung steht. Wieviel RAM benötigt diese Variante minimal für ein FAT-Dateisystem? Wie sieht es mit einem Low-Level_Zugriff aus? DANKE schon einmal.
Datum:
Hi Sven, ich denke das sollte so auf dem Atmega8 funktionieren, falls ich die Tabelle von Rolands Homage richtig interpretiert habe Ich spreche von der ersten Tabelle auf der folgenden Seite: http://www.roland-riegel.de/sd-reader/ Grüsse Nik
Datum:
Hi, hat jemand schon Verzeichnisse angelegt? Ich kriege es nicht richtig hin und habe immer alten Datenmüll in den Verzeichnissen. Danke!!! Gruß Holger
Datum:
Hallo zusammen, Tut mir Leid, dass ich mich in letzter Zeit nicht beteiligt habe. Mit Semesteranfang und Umzug hatte ich einiges zu tun. Vielleicht kann ich nächste Woche wieder was am SD-Reader machen. Dann könnte ich auch mal eine Funktion zum Anlegen von Verzeichnissen implementieren. Hier plagen sich ja anscheinend einige Leute damit rum... ;-) Viele Grüße, Roland
Datum:
Angehängte Dateien:So, wie versprochen zur Abwechslung mal wieder eine neue Version des sd-reader, zu finden im Anhang oder auf meiner Homepage http://www.roland-riegel.de/sd-reader/. Änderungen sind insbesondere: - Anlegen/Löschen von Verzeichnissen. - Löschen neu allokierter Cluster für Verzeichniseinträge. - Keine Verwendung von printf(). - malloc()/free() sind jetzt optional. Für Handles kann nun auch statischer Speicher verwendet werden. Bei Problemen bitte hier melden. Viel Spaß damit... Gruß, Roland
Datum:
Seit etwa 2 Monaten verwende ich die ältere Version von 20060319 in einem eigenen Projekt. Alles läuft sehr stabil und zuverläßig. Danke an Roland noch einmal dafür! Nun ist in meinem Projekt etwas aufgetreten womit ich zu Anfang überhaupt nicht gerechnet habe: die Datenflut ist einfach zu groß. Alles in einer einzigen Datei im root zu speichern war zwar einfach umzusetzen aber nicht besonders klug. Aufgrund der Größe macht ein Download auch bei 115k nun keinen Spaß mehr. Kein Problem dachte ich, die neue Version von 20061101 nehmen und alles in einzelne Verzeichnisse packen. Doch damit habe ich einige Probleme: Wenn ich z.B. ein neues Verzeichnis anlege mit "mkdir Test", zeigt ein "ls" noch korrekt an das es wirklich angelegt wurde. Aber beim hineingehen mit "cd Test" und "ls" bleibt alles in einer Endlosschleife hängen. Der erste Eintrag wird ständig wiederholt. Nur ein Reset erlöst den uC. Was mich stutzig werden läßt: Nehme ich die Karte und erzeuge im Kartenleser unter XP ein gleich lautendes Verzeichnis, dann zurück zum uC, zeigt "ls" es korrekt an. Ein "cd Test" und "ls" zeigt erwartungsgemäß die Einträge "." und ".." an. Dann zurück mit "cd.." und "rm Test" um das Verzeichnis zu löschen. Aber jetzt kommt der Hammer: "mkdir Test" und "ls" funktioniert jetzt... Die Karte habe ich mehrmals mit dem SDFormatter V1.2 formatiert. Einen "sync" nach jeder Eingabe habe ich auch nicht vergessen. Der uC und die Karte haben genug 'Saft'. ;) Für jemanden der mit Dateisystemen nicht per 'Du' ist so wie ich ist der Quelltext auch wenn er so gut strukturiert ist wie im SD-Reader nicht so einfach zu durchschauen. Deswegen meine Frage an Roland: Kannst Du mir bitte helfen dem Problem auf den Grund zu gehen? Möglicherweise könnten einige printf's an der richtigen Stelle helfen. Torsten
Datum:
Hallo André Kronfeldt, kiffen kann auch gesundheitsförderlich sein. In den Niederlanden werden bei bestimmtne Krankheiten z.B. MS nicht Interferoon und Opium sondern das Kiffen als Medikament empfohlen. Spezielle Züchtungen mit gesundheitsförderlichen Tendenzen statt Chemiekeule und Abhängigkeit. Spritzen kann man nur 2 Jahre. Rauchen kann man das ganze Leben lang. Roland weiter so. Denn in Zukunft gibt es CF Karten mit 8GB,16GB,32GB was ist mit denen.
Datum:
Hallo Torsten, Bezüglich Deines Problems habe ich nicht auf Anhieb eine Idee. Allerdings kenne ich im aktuellsten sd-reader einen Bug, der Probleme mit neuen Verzeichnissen im Zusammenspiel mit Windows XP bereitet. Vielleicht hilft das Beheben dieses Fehlers bei Deinen Problemen weiter. Ich werde Dir heute oder morgen näheres per Mail zuschicken. Irgendwie werden wir das schon hinbekommen... Gruß, Roland
Datum:
@ T.S.: Hast Du die defekte Karte wieder reaktivieren können oder eine Lösung für das Ziehen der Karte beim Schreiben gefunden ?
Datum:
Hallo zusammen Ist es möglich die SD-Karte an einem anderen Port und somit nicht mit dem Hardware SPI des AVR zu betreiben mit dem Code von Roland Riegel? In sd_raw.c wird ja das SPCR Register entsprechend konfiguriert...
Datum:
@ Pete 1) Nein. 2) Nein. Das habe ich auch noch nie gewagt. Mein Problem war ein anderes - nicht ausreichende Spannungsversorgung, siehe weiter oben. Die Lösung: aufpassen/vermeiden. ;) PS: Meine Mail blieb von Dir bis heute unbeantwortet. Torsten
Datum:
@Adrian, Klar geht das. Du müsstest jedoch Software-SPI verwenden. Nach kurzer Lektüre des Interface-Timings sollte das aber kein Problem sein. Gruß, Roland
Datum:
@Torsten: Sorry, eine PM ist an Dich unterwegs. Für das Ziehen der Karte oder Ausschalten habe ich eine kleine LED installiert, die mir anzeigt, wenn gerade nicht geschrieben wird. So richtig Austesten konnte ich das aber noch nicht. Defekte Karte ist an Kingston unterwegs :) Viele Grüße, Pete
Datum:
Wow ! Kingston hat eine neue Karte geschickt ! DAS nenne ich Service und Schnelligkeit !!! (freu) Montag abgeschickt und Donnerstag die neue Karte in der Hand. Besser geht´s nicht :-)
Datum:
Hallo, entschuldigt bitte die naive Frage aber leider fehlt mir der Durchblick: kann ich jetzt in Windows XP ein Paar Bitmap-Dateien erstellen, auf einer SD-Card speichern (mit einem ganz normalen USB-Kartenleser für den PC), um danach irgendeine beliebige dieser .bmp-Dateien mithilfe des Programms von Roland mit einem Mega8 auslesen? Anders gesagt, ich will einfach Paar .bmp Dateien bequem am PC erzeugen, die dann mit einem Mega auf einer LED-Matrix angezeigt werden werden, als Speichermedium eben die SD-Card. Es ist nur Lesen seitens des Mega nötig, er wird nicht auf die Karte schreiben. Bedeutet die FAT16 Unterstützung dieses Programms, dass ich eben so vorgehen kann und die .bmp-Dateien direkt vom PC auf der Karte kopieren kann, ohne sie irgendwie konviertieren zu müssen?
Datum:
Du musst sie nur im µC wieder zu raw dekodieren, was aber nicht äußerst schwer ist.
Datum:
@emil, Wenn der Mikrocontroller weiß, wie er das bmp-Format dekodieren/anzeigen kann, dann lautet die Antwort "Ja". Mein FAT16-Code liest exakt die selben Daten von der Karte, die das Grafikprogramm auf dem PC in die Datei auf der SD-Karte geschrieben hat. Gruß, Roland
Datum:
@Roland, Hauke: danke, genau das brauche ist; mein µC weiss schon, wie er mit .bmp die LED Matrix steuert, nur schreibe ich sie z.Z. im Flash vom µC. Ich mach'mich jetzt an die Arbeit mit der SD-Karte.
Datum:
Angehängte Dateien:
Hallo zusammen,
Es gibt wieder eine neue Version im Anhang und wie gehabt unter
http://www.roland-riegel.de/sd-reader/
Vorsicht: Die vorgenommenen Änderungen korrigieren Fehler im FAT16-Code
bei der Erstellung von neuen Verzeichnissen. Wenn Ihr eine alte Version
nutzt und die Funktion fat16_create_dir() verwendet, solltet Ihr auf
diese Version aktualisieren, sonst droht Datenverlust!
Viele Grüße,
Roland
Datum:
Hallo, verwende den fat16 Zugriff von Roland Riegel. Im Prinzip funktioniert alles prima, allerdings habe ich Probleme wenn ich der Übersicht halber die verschiedenen Funktionsaufrufe zum erzeugen eines files in eine eigene Funktion packe. Der entstprechende Funktionsprototyp sieht folgendermassen aus: uint8_t create_log_file(struct fat16_fs_struct* fs, struct fat16_file_struct* fd1) In der Funktion erzeuge ich meinen gewünschten Dateinamen und mit der Funktion fat16_create_file die gewünschte Datei. Mit fd1 = fat16_open_file(fs, &file_entry) öffne ich die Datei und weise den als Paramter übergebenen Pointer struct fat16_file_struct* fd1 zu. Wenn ich nun in main nach Aufruf von create_log_file folgende Zeilen ausführe wird nichts in die Datei geschrieben. struct fat16_file_struct* fd1; create_log_file(fs, fd1); char buffer[]="test"; int8_t data_len = sizeof(buffer); /* write text to file */ fat16_write_file(fd1, (uint8_t*) buffer, data_len); sd_raw_sync(); Wenn ich allerdings die selben Zeilen unmittelbar vor der return Anweisung in create_log_file einfüge wird der String "test" wie gewünscht in die Datei geschrieben. Wird der Zeiger fd1 nach Beendigung von create_log_file ungültig (bzw. der Bereich wo der Zeiger hinverweist)? Oder wo könnte das Problem liegen? Vielen Dank für eure Tips M.
Datum:
Hallo M.,
Das Problem liegt in Deinem falschen Verständnis der Argumentenübergabe
in C. Du änderst fd1 nur innerhalb der Funktion. Wird diese verlassen,
behält sie ihren alten Wert.
Zwei Möglichkeiten:
1. Die elegantere
struct fat16_file_struct* create_log_file(struct fat16_fs_struct* fs)
{
/* ... */
struct fat16_file_struct* fd = fat16_open_file(...);
/* ... */
return fd;
}
2. Die Abänderung Deiner Funktion
uint8_t create_log_file(struct fat16_fs_struct* fs, struct
fat16_file_struct** fd)
{
/* ... */
*fd = fat16_open_file(...);
/* ... */
return 1;
}
Bei weiteren Fragen suche nach einem beliebigen C-Tutorial im Web.
Gruß,
Roland
Datum:
Hallo, um meine Daten die ich auf die SD Karte schreibe zu komprimieren, lege ich die einzelnen Variablen die ich verwende nicht direkt auf der Karte ab sondern beschränke die Anzahl der Bits auf den tatsächlichen maximalen Wertebereich. Die Bits der verschiedenen Variablen verknüpfe ich zu einem Stream. Über einen Descriptor der jedem neuen Datensatz vorausgeht ist die Länge der einzelnen Datenfelder definiert. Im Prinzip scheint auch alles zu funktionieren, allerdings habe ich hin und wieder beim dekodieren nach einer wechselnden Anzahl von Datensätzen keine vernünftigen Daten mehr. Ich vermute die Ursache darin, dass beim speichern auf die Karte dann an dieser Stelle Daten verloren gegangen sind. Der Decodier Algorithmus kommt dann durcheinander weil er durch das fehlende Byte um 8 Bit verschobene und somit falsche Bits für den Descriptor einliest. In meiner Funktion zum abspeichern überprüfe ich zwar ob das zu speichernde Byte auch geschrieben wird, aber bekomme dort keine Fehlermeldung. Habe sowohl mit als auch ohne SD_RAW_WRITE_BUFFERING das gleiche Problem. Meine Funktion zum speichern und einen exemplarischen Aufbau des Aufrufs findet ihr im Anhang. Tips? Oder suche ich den Fehler an der falschen Stelle? Sind die Daten sicher auf der Karte gespeichert wenn fat16_write_file() die richtige Anzahl von geschrieben Daten als Rückgabewert liefert? Auf der anderen Seite bin ich mir relativ sicher, dass die Kompression und Dekompression richtig funktionieren. Schwierig weil der Fehler mehr oder weniger zufällig ist. Danke M.
Datum:
Hallo M., Was mir an Deinem Code auffällt ist, dass data_block nie initialisiert wird. Je nachdem, was da nach dem Reset oder durch den vorhergehenden Datenstrom noch drinsteht, gibt es nur noch Datenmüll. Gruß, Roland
Datum:
Hallo Roland, ich habe eine kleinen Service-Request für Deine Bibliothek. Ich arbeite öfter mal abwechselnd mit dem ATMega16 und ATMega644 und da haben leider die SPI-Register unterschiedliche Namen. Könntest Du es vielleicht etwas generischer in der Bibliothek bauen ? Das wäre prima :-) Gruss, Pete
Datum:
@Pete,
Die unterschiedlichen Namen sind mir bisher nicht untergekommen.
Du kannst das in der Zwischenzeit aber auch selber machen. In
sd_raw_config.h definierst Du Dir z.B.
#define SPI_SPCR SPCR
#define SPI_SPSR SPSR
für den ATmega16, und entsprechendes für den ATmega644.
In sd_raw.c ersetzt Du dann einfach alle Vorkommen von SPCR durch
SPI_SPCR und SPSR durch SPI_SPSR. Entsprechendes für die einzelnen Bits,
falls nötig.
Gruß,
Roland
Datum:
Ja stimmt sollte besser static uint8_t data_block = 0x00; in der Deklaration heißen. Allerdings würde ein abweichender Startwert ja nur den ersten gespeicherten Wert beeinflussen. Das von mir geschilderte Problem tritt aber erst irgendwann später auf. M.
Datum:
Hmm, mir ist grad eingefallen, dass afaik statische Variablen ja doch einen Standard-Initialisierungswert bekommen. Was genau Dein Problem sein könnte, weiß ich sonst aber auch nicht. Da mein FAT16-Code mittlerweile doch recht gut getestet sein sollte, glaube ich aber trotzdem, dass das Problem eher in Deinem Code liegt. Gruß, Roland
Datum:
Kann gut sein, werde mich wohl auch damit beschäftigen bis ich die Ursache gefunden habe ;-) Kann es zu Problemen mit der SD Card Kommunikation kommen wenn während eines Schreibzykluses ein Interrupt ausgelöst wird? Ich empfange einen kontinuierlichen Datenstream über UART. Im Unterschied zu deiner Beispielkonsolenanwendung treten also immer Daten an der seriellen Schnittstelle auf und es kann dementsprechend auch während eines Schreibzykluses ein Interrupt ausgelöst werden. Gruss M.
Datum:
Hmm, kann ich nicht mit Bestimmtheit ausschließen, aber ich denke nicht, dass Interrupts während eines SPI-Transfers Probleme machen. Der SPI-Bus ist unkritisch bzgl. des Timings und die Ansteuerung der Karte eigentlich auch. Hast Du die Bitstream-Algorithmen denn schonmal ohne die UART ausprobiert? Also zum Beispiel an Hand von festen oder aufgezeichneten Daten? Gruß, Roland
Datum:
Hallo Roland,
ich habe eine Frage zu dem Offset Parameter bei fat16_seek_file.
Wenn ich ein append machen will, geht das dann so? :
int32_t offset = 0; // zero bytes from the end of the file ==> append
if(!fat16_seek_file(fd, &offset, FAT16_SEEK_END) { ... }
Das klappt auch, wenn das File leer ist ?
Beste Grüße,
Pete
Datum:
Pete wrote: > Wenn ich ein append machen will, geht das dann so? : Ja, genau so funktioniert es. > Das klappt auch, wenn das File leer ist ? Äh... Sollte es. Gibts Probleme? Gruß, Roland
Datum:
Hi Roland, erst mal.....super Code den Du da hast!!! Ich benutze Deinen neuesten Code vom 20.01.07 auf einem Arm7. Funktioniert alles prima. Das einzige Problem das ich habe ist, wenn ich Verzeichnisse erstelle kann ich diese nicht unter Windows XP löschen da Windows mir immer sagt, das das Verzeichnis nicht leer ist. Selbst erstellte Dateien zu löschen funktioniert prima auch in ertellten Verzeichnissen. Hast Du eine Idee? Danke im voraus!!! Gruß Mille
Datum:
Könntest Du mir bitte mal schildern, was Du genau gemacht hast, um den Fehler zu bekommen? Eine Schritt-für-Schritt-Anleitung wäre am besten, damit ich den Fehler reproduzieren und nachvollziehen kann. Als Randnotiz: Auf einem Arm hast Du vermutlich mehr RAM verfügbar als ich auf einem mega168. Deshalb wäre vielleicht die Verwendung eines anderen FAT16-Treibers performanter, da ich bei mir nur wenige Strukturen des Dateisystems zwischenpuffern kann. Grüße, Roland
Datum:
Angehängte Dateien:Hi Roland, Dein Code funktioniert soweit prima außer dem einem Problem und wenn was funktioniert sollte man nicht umsteigen! ;-))) Wenn ich einfach ein Verzeichnis mit dem Namen "test" so anlege habe ich das Problem: struct fat16_dir_entry_struct dir_entry; fat16_create_dir(dd, "test", &dir_entry); Egal ob ich einfach nur ein Verzeichnis alleine anlege oder eine Datei hineinschreibe. Die Datei kann ich dann unter Windows XP löschen....das Verzeichnis allerdings nicht. Auch wenn ich nur ein Verzeichnis anlege ohne eine Datei dort rein zu schreiben! Windows meckert dann immer!!! Siehe das JPEG im Anhang. Auch wenn ich das Häkchen unter Schreibgeschützt weg mache kann ich das Verzeichnis nicht löschen. Vielleicht hast Du ja noch eine Idee? Gruß Mille
Datum:
Ok, danke. Ich werde mir das mal anschauen, kann Dir aber noch nicht sagen, wann ich Zeit dafür finde.
Datum:
Hallo, ich habe Probleme beim initialieren meiner Sd Karten. Wenn ich die Karten unter Windows formatiere kommt es relativ oft vor, dass die Karten nicht richtig funktionieren. Error beim Filessystem öffnen oder mein ganzes Program bleibt schon bei der Initialisierung hängen. Formatiere ich unter unix gehen die Karten dann vorerst wieder. Woran liegt das? Was verwendet ihr unter Windows zum formatieren eurer Karten? Bei einer meiner Karten habe ich zudem das Problem, dass ich hin und wieder nach Verwendung mit dem Mikrocontroller die Karte nicht mehr formatieren und die Dateien löschen kann - Fehlermeldung die Karte ist schreibgeschützt. Danke Jeremy
Datum:
@Mille, Gestern habe ich Dein Problem nachvollziehen können. Nach einigem Gefummel mit dem Diskeditor habe ich auch den Grund gefunden. Windows mag die LFN-Verzeichniseinträge nicht, die meine Software für die "."- und ".."-Links erzeugt. Ich werde mal schauen, wie ich das möglichst einfach beheben kann, oder ob ich nicht mehr für alle Dateien einen LFN-Eintrag anlege. In den nächsten Tagen wirds dann wohl eine neue Software-Version für den sd-reader geben. Gruß, Roland
Datum:
Hallo Roland, da ich demnächst einen offline Temperaturlogger bauen wollte, würde ich gerne die Messwerte auf SD-Card speichern. Was ich auf deiner Homepage so sehe, sieht sehr gut aus. Respekt. Zu den Eagle Files hätte ich zwei Fragen: verwendest du von Reichelt den "Connector 21"? Wie auch immer, wozu der Anschluss von "Pin" 10, 11, 12? Die sind doch für den Schreibschutz der Karte, oder? Wird der ausgewertet, bzw. benötigt man denn überhaupt? Wenn ich die Dokus zur SD-Karte richtig gelesen habe, dann obliegt die Auswertung des Schreibschutzes nur der Software, es wird also nichts hardwaremäßig an der Karte ausgeschaltet. Insofern: da ich eh auf die Karte schreiben möchte, kann ich mir die 2 Pins (+ 1 GND) auch sparen. Gruß, Dirk
Datum:
@Dirk > Was ich auf deiner Homepage > so sehe, sieht sehr gut aus. Respekt. Danke. > Zu den Eagle Files hätte ich zwei Fragen: verwendest du von Reichelt > den "Connector 21"? Ja, richtig. > Wie auch immer, wozu der Anschluss von "Pin" 10, 11, 12? > Die sind doch für den Schreibschutz der Karte, oder? Wird der > ausgewertet, bzw. benötigt man denn überhaupt? Genau, das sind Schließer zum Erkennen ob eine Karte gesteckt ist und in welcher Position sich der Schreibschutzschalter befindet. Ausgewertet wird er von meiner Software schon (zumindest rudimentär), wobei das ganze optional ist. Du kannst die entsprechenden #defines in sd_raw_config.h auch zu 0 bzw. leer definieren. Dann ist quasi immer eine nicht schreibgeschützte Karte gesteckt. > Wenn ich die Dokus zur > SD-Karte richtig gelesen habe, dann obliegt die Auswertung des > Schreibschutzes nur der Software, es wird also nichts hardwaremäßig an > der Karte ausgeschaltet. Insofern: da ich eh auf die Karte schreiben > möchte, kann ich mir die 2 Pins (+ 1 GND) auch sparen. > Richtig und wieder richtig :) Viele Grüße, Roland
Datum:
Hallo Roland, danke für die Antwort. Habe eben bei Reichelt die passenden Bauteile (mit kleinen Änderungen) bestellt. Gönne mir den Luxus der Pegelanpassung mittels Transistoren und extra Spannungsregler. Das bischen neu layouten war auch kein Thema. Was mir dabei aufgefallen ist: die Library in deiner Zip Datei der ersten Version enthält den Connector, allerdings scheinen die "Platzierungen/Pins" des Connectors nicht zu stimmen (sind um 0,05inch verrückt), so dass er im schematic nicht angeschlossen werden kann. War allerdings kein Problem: einfach das device mit verschobenen Pins neu erstellen, Rest passt wohl hoffentlich (jedenfalls nach chinesischem Datenblatt von Reichelt). Insofern bleibt unterm Strich nur zu sagen: Respekt vor deiner Leistung die Software dazu zu entwicklen und dich so in die Materie einzuarbeiten! Gruß, Dirk
Datum:
Ja, bzgl. der Library hast Du recht. Habe die nicht selbsterstellt und hatte damals auch noch keine Erfahrung mit der Bearbeitung. Ich habe aber rausgefunden, dass Eagle eine korrekte Verbindung erstellt, wenn man das Netz am verschobenen Pin anfängt zu zeichnen. Nur wenn man das Netz an dem Pin abschließen will, funktioniert das nicht richtig. Gut, dass Du ordentliche Pegelwandler und nen eigenen Spannungswandler vorsiehst. Ich hatte mit dem Provisorium von Ulrich Radig zwar kaum Probleme, das kann aber auch an den von mir verwendeten Karten liegen. Wenn die Karte während dem Schreibvorgang Stromspitzen von 100 oder 200 mA braucht, ist das mit den Dioden wirklich nicht mehr optimal. Gruß, Roland
Datum:
Angehängte Dateien:
@Mille und alle anderen,
Es gibt eine neue Version der sd-reader-Software auf meiner Homepage
http://www.roland-riegel.de/sd-reader/
oder im Anhang.
Ich empfehle eine Aktualisierung, da ich einige nicht ganz unwichtige
Fehler gefunden und behoben habe:
* Windows kann jetzt die vom sd-reader angelegten Ordner löschen.
* Falls der Dateiname mit dem Byte 0xe5 beginnt, wird dies nun korrekt
gehandhabt. (Dieses Byte dient normalerweise dazu, die Datei als
gelöscht zu markieren.)
* fat16_clear_cluster() löscht nun korrekt. Zuvor wurden 16 von 32 Bytes
nicht richtig auf 0 gesetzt.
* fat16_delete_file() gibt nun auch bei leeren Dateien den richtigen
Wert zurück.
Viele Grüße,
Roland
Datum:
Übrigens gute Meldung bezüglich FAT (zumindest in D): http://www.heise.de/newsticker/meldung/86102
Datum:
@Roland, kurzes feedback. Funktioniert alles prima!!! Super Arbeit!!! ->froi<- Gruß Mille
Datum:
@Gast, Ja, mein vServer ist down. Der Host hatte nach Auskunft des Providers einen Kernel-Panic, jetzt muss das Datei-System überprüft werden. @Mille, Danke! Gruß, Roland
Datum:
Also ich nutz seit einiger Zeit ne Compactflash als Festplatte. Und habe noch keine Probleme gehabt. Ich denke der Wert 100.000 ist der Garantierte Wert, die FLashs kommen sicher noch höher. Dank an Roland Riegel und die gesammte Open-Souce, Mein Datenlogger funktionert endlich. Was ich noch nicht verstehe ist, warum ich nach jedem ADC-Cannel wechsel ne Dummymessung machen muß.
Datum:
Hallo Roland, wie kann ich unter Windoes XP die SD-Karte als FAT16 formatieren?
Datum:
Hallo Michael, Beim Formatieren sollte Windows für Karten <= 2GB meines Wissens nach automatisch FAT16 verwenden. Rechtsklick auf Laufwerk und "Formatieren..." wählen. Ansonsten von einer Linux-CD booten und fdisk sowie mkdosfs verwenden. Gruß, Roland
Datum:
Vielen Dank für Deine schnelle Antwort,Roland. Ich werde es wohl mit Linux versuchen müssen, da ich mit Windows bisher wenig, oder keinen Erfolg erzielen konnte. Gruss,Michael
Datum:
Hmm, warum willst Du die Karte eigentlich neu formatieren? Die werden doch schon mit einem FAT16-Dateisystem ausgeliefert, welches einwandfrei mit dem sd-reader funktionieren sollte. Roland
Datum:
Hallo Roland, Du hast vollkommen Recht. Jedoch sind meine SD-Karten bereits schon mit dem FAT 32 formatiert. Versuche jetzt deinen Vorschlag. Viele Grüsse, Michael
Datum:
hallo, hat jemand ein ein schema fuer mich? moechte das ganze mit nem atmega16 ausprobieren, da sind die boardlayouts leider nicht sehr hilfreich. mal das ganze dann schnell mit eagle um/nach und stells hier rein. danke hansl
Datum:
Hallo Guido, Guido Fischer wrote: > Glückwunsch zum Source - funktioniert! > Danke! > Ich hab mein Arthernet damit eben wiederbelebt da ich dort ja die MMC > fest drauf habe. Chip Select über das CPLD funktioniert leider nicht, > da das Programm nach Aktivierung des XMEM nicht mehr will. > Meinen Respekt für Arthernet. Eine Menge Arbeit und sehr professionell. Zu XMEM kann ich Dir nicht viel sagen, da ich es zwar schonmal benutzt habe, die Schaltung jedoch keinen SD-Sockel hat. Was heißt, dass das Programm nicht mehr will? > Ich habe eine günstige 1GB Karte die auf Anhieb läuft und eine 512MB > Karte die sich nur durch zahlreiche Resets zur Antwort überreden lässt. > Ich versuch gerade herauszufinden, woran's liegt, komme aber nicht > weiter da mein JTAG streikt und das Arthernet Modul auch noch rumzickt. > Wie wird denn die Versorgungsspannung für die Karte bereitgestellt? Ich selbst habe die 3,3V mittels zweier Dioden erzeugt und hatte damit keine Probleme. Andere berichteten damit jedoch teils von immensen Problemen, da die Karten oft sehr hohe Spitzenströme von 100-200mA brauchen, bei denen die Spannung einbricht. Ein eigener Spannungsregler wäre am besten. > Bei einer recht vollen Karte konnte ich keine Dateien mehr anlegen. Ich > hatte drei Ordner mit zig mp3 Files und im Root versucht eine Datei > anzulegen. Wurde ohne Fehler quittiert aber die Datei war nicht da. > Sobald ich das reproduzieren kann, schicke ich Dir dazu passende Infos. > Ok, danke. Eventuell wäre auch ein Kartenimage sinnvoll. > Jetzt guck ich erst mal, warum der JTAG nicht will :-/ > > Gruß, Guido Viele Grüße, Roland
Datum:
Servus Guido, Guido Fischer wrote: >> Wie wird denn die Versorgungsspannung für die Karte bereitgestellt? > > Separater 3.3V Spannungsregler und SPI über 74LVX125 entkoppelt. > Ok, das sollte mehr als ausreichen. Vielleicht ist die Karte selbst etwas zickig und man sollte die Anzahl der Initialisierungsversuche oder die Wartezeiten innerhalb von sd_raw_init() nach oben setzen. >> [Kartenimage] > > Bevor ich mir die Arbeit mache rauszufinden, wie ich das unter Windoof > hinkriege, schick ich Dir die 2,99 EUR Karte eher per Post ;-) > Entweder so, oder mit dem Windows-Port von dd, siehe http://www.chrysocome.net/dd Falls Du es auf diesem Weg machen willst, könnte ich Dir ein bisschen FTP-Platz bereitstellen. > Btw. ich hab jetzt meinen RTC am rennen und wollte den Vorschlag > machen, neue Dateien optional mit einem Datum zu versehen. Ich hab zwar > schon mal versucht in den Structs die passenden Stelle zu finden, aber > das ist mir zu abstrakt - da kennst Du Dich besser aus. > Bei mir im Code findest Du da nichts, weil ich das nicht vorgesehen habe. Es sollte aber relativ einfach möglich sein, das zu implementieren. Allerdings würde ich das wieder mit #defines konfigurierbar machen, da solch ein Feature für die meisten Anwendungen überflüssig sein dürfte. Ich schau mir das bei Gelegenheit mal an. Allerdings würde ich darauf verzichten, auch noch die Zeiten des letzten Zugriffs oder der letzten Änderung aufzuzeichnen. Oder wüsstest Du eine vernünftige Anwendung dafür? Grüße, Roland
Datum:
Wegen SD formatieren: Gibts bei Panasonic http://panasonic.jp/support/audio/sd/download/sd_f...
Datum:
Hallo Guido, Hmm, das ist merkwürdig. Ich habe hier ein mega128 ENC28J60-Board liegen, welches SPI und XMEM verwendet. Wenn Du magst, kann ich Dir ja mal ein abgespecktes Grundgerüst von meinem Code schicken. Mittlerweile habe ich den sd-reader FAT16-Code so erweitert, dass das Erstellungsdatum und die -zeit gelesen und gesetzt werden kann. Durchgetestet habe ich das aber noch nicht. Viele Grüße, Roland
Datum:
Auf die Erweiterung mit Datum/Uhrzeit bin ich auch gespannt... Bei mir ist es so das der sd-reader in meinem eigenen Projekt seit geraumer Zeit erfolgreich läuft. Allerdings in einer älteren Version; das Problem mit Verzeichnissen unter m$ kann ich nachvollziehen wie hier gepostet wurde. Nun habe ich etwas Angst alle Dateien mit denen von einer neueren Version mit einem Schlag einfach zu ersetzten. Möglicherweise sind eigene 'Anpassungen' drin die ich einfach vergessen habe. Roland, könntest Du evtl. ein Diff zwischen den einzelnen Versionen mit veröffentlichen? Das wäre sehr hilfreich. Danke noch einmal für alles, Torsten
Datum:
@Guido,
Naja, ob das gleich Genialität beweist ;-)
@Torsten,
Bei Gelegenheit (sprich: dem nächsten Release) werde ich das machen. Bis
dahin kannst Du Dir auch selbst behelfen:
diff -ur [sd-reader_verzeichnis] [verzeichnis_mit_deinem_code] >
deine_aenderungen.patch
Oder z.B. auch:
diff -ur sd-reader_source_20061101 sd-reader_source_20070301 >
sd-reader_diff_20061101_20070301.patch
Zurückspielen tust Du das dann in dem Verzeichnis, wo der zu patchende
Code liegt:
patch -p1 -i deine_aenderungen.patch
Du kannst obiges auch noch um --dry-run ergänzen, um zunächst nur mal zu
sehen, ob es Konflikte geben wird.
Bei diesen Experimenten solltest Du vorher natürlich Backups machen...
Grüße,
Roland
Datum:
Hallo zusammen, @Guido: Die Probleme sind mir seinerzeit bei der Anpassung von Rolands SD Library nicht aufgefallen. Ich benutze auch dein Arthernet zusammen mit Rolands Library und einer 32MByte NoName MMC Karte und einer 128MByte NoName SD Karte. Die gehen beide problemlos. Ok, ich lese von der Karte. Der entscheidende Teil der sd_raw_config.h sieht bei mir so aus:
#elif defined(__AVR_ATmega64__) || \ defined(__AVR_ATmega128__) /* Attention: all pins must be defined for correct work */ #define configure_pin_mosi() DDRB |= (1 << PB2) #define configure_pin_sck() DDRB |= (1 << PB1) #define configure_pin_ss() DDRB |= (1 << PB0) #define configure_pin_miso() DDRB &= ~(1 << PB3) #define select_card() *pSPI_CS &= ~(1 << SPIP4) #define unselect_card() *pSPI_CS |= (1 << SPIP4) #else |
Zu JTAG kann ich leider nichts sagen ich benutze nur den ISP Anschluss. Tschau Michael
Datum:
Hallo zusammen, @Guido: Wieder mal zu schnell abgesendet. Der Code geht ja noch weiter:
#elif defined(__AVR_ATmega64__) || \ defined(__AVR_ATmega128__) /* Attention: all pins must be defined for correct work */ #define configure_pin_mosi() DDRB |= (1 << PB2) #define configure_pin_sck() DDRB |= (1 << PB1) #define configure_pin_ss() DDRB |= (1 << PB0) #define configure_pin_miso() DDRB &= ~(1 << PB3) #define select_card() *pSPI_CS &= ~(1 << SPIP4) #define unselect_card() *pSPI_CS |= (1 << SPIP4) #else #error "no sd/mmc pin mapping available!" #endif #define configure_pin_available() DDRB &= ~(1 << PB7), PORTB |= (1<<PB7) /* internen Pull-Up an PB7 aktivieren */ #define configure_pin_locked() DDRB &= ~(1 << PB6), PORTB |= (1<<PB6) /* internen Pull-Up an PB6 aktivieren */ #define get_pin_available() ((PINB >> PB7) & 0x01) #define get_pin_locked() ((PINB >> PB6) & 0x01) |
Der Pin available und locked funktionieren auf dem Arthernet auch. Tschau Michael
Datum:
Angehängte Dateien:@Guido, Torsten und andere Interessierte, Angehängt findet Ihr nun einen Patch, der das Erstellungsdatum von Dateien und Ordnern setzt. Er sollte funktionieren, allerdings konnte ich ihn nicht richtig testen, da 1. an meinem sd-reader keine RTC vorhanden ist und 2. mein kleiner mega168 durch die 5Byte größere fat16_dir_entry_struct mal wieder Platzprobleme im Stack bekommt. Vielleicht könntet Ihr die Änderungen mal antesten. Bitte ändert in fat16_config.h das define fat16_get_datetime ab, sonst wird immer der 01.01.2007 eingetragen. Viele Grüße, Roland
Datum:
> was nehm ich da für ein Programm unter Windows? ... das gleichnamige. ;) Wenn Du WinAVR installiert hast, guck mal unter utils\bin Torsten
Datum:
Oder guck einfach mal per Wordpad in die .patch-Datei. Das Format ist eigentlich selbsterklärend. Zur Not kannst Du es also per Hand mergen. Bin schon gespannt auf Eure Ergebnisse... Gruß, Roland
Datum:
Roland, Offen gestanden hat es mich erhebliche Überwindung gekostet um den neuen Code auszuprobieren. Sachen die gut laufen sollte man eigentlich nicht mehr anfassen. ;) Zuerst habe ich ein Update auf 20070301 gemacht. Per Hand so wie Guido, mit copy&paste nach dem diff zu der alten Version. 'patch' traue ich mich nicht auf meine Sourcen loszulassen. Dabei ist mir aufgefallen, daß Du die GPL entfernt hast. Was bedeutet das jetzt genau? Dann den neuen patch per Hand eingebaut. Aus Bequemlichkeit und/oder Vorsicht belasse ich erst einmal die Zeit so wie sie ist mit dem eingebauten #define fat16_get_datetime. Die Daten sind mir wichtig, ich möchte nichts riskieren. Das Datei-Datum jetzt vom RTC zu holen bedeutet einiges an meinem Proggi umzubauen. Ich habe dann einige neue Dateien mit dem AVR erzeugt. Anschließend die Karte in XP's Card-Reader eingesteckt. Kein Datum im Explorer. :( Cmd in XP ausprobiert: Ein 'dir' zeigt für eine Datei z.B. 01.01.1601 02:00 166.828 01.txt Bestimmt habe ich irgendwo einen typo. Nur wo? Kann ich evtl. an einer sinnvollen Stelle ein paar Bytes zur V24 schicken zum gucken was los ist? Oder muß ich die Karte neu formatieren (was ich eigentlich nicht glaube)? Hmm, bin etwas ratlos. Torsten
Datum:
Hallo Torsten, T.S. wrote: > Roland, > > Offen gestanden hat es mich erhebliche Überwindung gekostet um den > neuen Code auszuprobieren. Sachen die gut laufen sollte man eigentlich > nicht mehr anfassen. ;) > Nun, gegen diese Ängste gibt es Versionskontrollsysteme oder, in der simpelsten Form, Backups :) > Zuerst habe ich ein Update auf 20070301 gemacht. Per Hand so wie Guido, > mit copy&paste nach dem diff zu der alten Version. 'patch' traue ich > mich nicht auf meine Sourcen loszulassen. > Naja, ich denke die Wahrscheinlichkeit, dass Du per Hand einen Fehler machst, ist größer als die Wahrscheinlichkeit, dass "patch" etwas falsch abändert und keine Konflikte meldet. > Dabei ist mir aufgefallen, daß Du die GPL entfernt hast. Was bedeutet > das jetzt genau? > Was meinst Du mit "die GPL entfernt"? Welche Version hattest Du vorher genau? Der Code ist und bleibt unter der GPL. Soweit ich mich erinnere, habe ich vor einigen Versionen lediglich mein Copyright und einen Vorspann zu jeder Datei hinzugefügt. > Ich habe dann einige neue Dateien mit dem AVR erzeugt. Anschließend die > Karte in XP's Card-Reader eingesteckt. Kein Datum im Explorer. :( > > Cmd in XP ausprobiert: Ein 'dir' zeigt für eine Datei z.B. > > 01.01.1601 02:00 166.828 01.txt > 1601? Das kann FAT eigentlich gar nicht darstellen. Kontrolliere vielleicht nochmal nach, ob Du die Funktionen fat16_set_file_creation_date() und fat16_set_file_creation_time() korrekt übernommen hast. > Bestimmt habe ich irgendwo einen typo. Nur wo? > Kann ich evtl. an einer sinnvollen Stelle ein paar Bytes zur V24 > schicken zum gucken was los ist? Oder muß ich die Karte neu formatieren > (was ich eigentlich nicht glaube)? > Du könntest innerhalb von fat16_create_file() nach dem Aufruf der beiden oben genannten Funktionen den Inhalt der Variablen dir_entry->creation_date und dir_entry->creation_time ausgeben lassen. Wenn Du noch eine alte Version Deines Codes hast, könntest Du auch mal einen Patch gegen Deinen jetzigen Code erstellen und diesen mit meinem geposteten Patch vergleichen. > Hmm, bin etwas ratlos. > Das wird schon ;-) Gruß, Roland
Datum:
Hallo Roland, > Was meinst Du mit "die GPL entfernt"? Welche Version hattest Du vorher > genau? Eine ältere Version, welche genau habe ich vergessen. Da habe ich etwas falsch verstanden. Bitte entschuldige. Btw wenn Du CVS verwendest, könnte man $Id$ einfügen, das zeigt die letzte Änderung an. Um Tippfehler auszuschließen habe ich jetzt auf die Version 20070301 patch losgelassen: patch -i sd-reader_fat16-time.patch.txt Die 3 betroffenen Dateien habe ich in mein Projekt kopiert. Zusätzlich noch etwas debug-code in fat16_create_file und fat16_create_dir spendiert: ... fat16_get_datetime(year, month, day, hour, min, sec); fat16_set_file_creation_date(dir_entry, year, month, day); fat16_set_file_creation_time(dir_entry, hour, min, sec); printf_P((PSTR("%02d.%02d.%04d %02d:%02d:%02d\r\n")), day, month, year, hour, min, sec); ... Auf der Konsole so wie es sein sollte: 01.01.2007 00:00:00 beim erzeugen von Dateien oder Verzeichnissen. Also arbeitet die Funktion soweit. Trotzdem das gleiche wie gestern beschrieben. Vielleicht geht's mit einer anderen Karte, mal sehen. Torsten
Datum:
Hi Torsten, > Btw wenn Du CVS verwendest, könnte man $Id$ einfügen, das zeigt die > letzte Änderung an. > Ich verwende Subversion, aber da geht das auch, ja. > Um Tippfehler auszuschließen habe ich jetzt auf die Version 20070301 > patch losgelassen: > patch -i sd-reader_fat16-time.patch.txt > > Die 3 betroffenen Dateien habe ich in mein Projekt kopiert. Zusätzlich > noch etwas debug-code in fat16_create_file und fat16_create_dir > spendiert: > Das heißt, im Prinzip verwendest Du jetzt meinen Original-Code? Schön. > ... > fat16_get_datetime(year, month, day, hour, min, sec); > fat16_set_file_creation_date(dir_entry, year, month, day); > fat16_set_file_creation_time(dir_entry, hour, min, sec); > > printf_P((PSTR("%02d.%02d.%04d %02d:%02d:%02d\r\n")), > day, month, year, hour, min, sec); > ... > > Auf der Konsole so wie es sein sollte: > 01.01.2007 00:00:00 > beim erzeugen von Dateien oder Verzeichnissen. Also arbeitet die > Funktion soweit. Alles was das aussagt ist, dass fat16_get_datetime() funktioniert, und das sind ja im Moment nur einfache Zuweisungen. Ich wollte explizit den Wert von dir_entry->creation_date/time wissen. Der sollte 0x3621 (für 01.01.2007) bzw. 0x0000 (für 00:00:00 Uhr) sein. Nur die Werte innerhalb von dir_entry werden dann auch von fat16_write_dir_entry() auf die Karte geschrieben. > Trotzdem das gleiche wie gestern beschrieben. > Vielleicht geht's mit einer anderen Karte, mal sehen. > Ich glaube nicht, dass das an der Karte liegt. Das hat nichts mit der physikalischen Ebene zu tun. Grüße, Roland
Datum:
Hallo Roland, > Das heißt, im Prinzip verwendest Du jetzt meinen Original-Code? Schön. Yep. > Alles was das aussagt ist, dass fat16_get_datetime() funktioniert, und > das sind ja im Moment nur einfache Zuweisungen. Ich wollte explizit den > Wert von dir_entry->creation_date/time wissen. Der sollte 0x3621 (für > 01.01.2007) bzw. 0x0000 (für 00:00:00 Uhr) sein. Nur die Werte innerhalb > von dir_entry werden dann auch von fat16_write_dir_entry() auf die Karte > geschrieben. Achso. Schon wieder habe ich etwas falsch verstanden, ich bitte abermals um Entschuldigung. Die beiden printf_P's habe ich nun geändert, sind noch an der gleichen Stelle: printf_P((PSTR("date: 0x%04x time: 0x%04x\r\n")), dir_entry->creation_date, dir_entry->creation_time); Ich hoffe das war richtig. Heraus kommt: date: 0x3621 time: 0x0000 > Ich glaube nicht, dass das an der Karte liegt. Das hat nichts mit der > physikalischen Ebene zu tun. Wie Du richtig vermutet hast hat sich mit einer anderen Karte nichts geändert. Debuging ist keine einfache Sache und kann evtl. länger dauern weil alles mögliche dafür in Frage kommen kann. Wir könnten versuchen der Sache auf den Grund zu gehen wie schon einmal per PM wenn Du möchtest. Es schreibt sich halt einfach leichter. Torsten
Datum:
Angehängte Dateien:Hallo zusammen, da hier alle SD-Karten Kompetenzen versammelt sind trau ich mich mal eine frage zu stellen. Ich bestreite gerade ein Projekt indem ich eine SD-Karte mit Fat16 formatierung an ein Tricore 1130 µC anbinden soll. Im wesentlichen hab ich die Sourcecodes von Ulrich Radig übernommen, will sagen ich hab sie an meinen µC angepasst. Da mein µC auf 3,3V läuft hab ich die SD-Karte quasi Eins zu Eins an den Port geklemmt. Ich habe jetzt allerdings ein problem bei der Initialisierung der Karte. Nachdem ich die mind. 74 Clocks an die SD-Karte bei CS=High schick, sende ich ja das CMD 0 bei CS=LOW. Sämtliche Übertragungen der Bytes hab ich mit dem Oszi überprüft. Nach Plan sollte die Karte dann ja 0x01hex zurücksenden. Die Antwort die ich bekom ist allerdings 0x3fhex. Meine Frage lautet nun: Wie kann die SD-Karte mir z.b. einen Illigal Command Error zurücksenden, obwohl ich doch 6 Bytes für Commando 0 hinschick. Ich komm einfach nicht dahinter was mir die Karte damit sagen will. Meinen Quellcode habe ich mal angehängt. Für eine erleuchtende Antwort wäre ich euch dankbar.
Datum:
Mir fällt etwas auf in
while(sd_write_command(cmd)!=0x01)
{
if(Timeout++ >= 10) <--- [*]
{
return (1);
}
}
[*] Das Timeout ist auf jeden Fall zu kurz. Ich glaube irgendwo mal
gelesen zu haben das das Aufwecken der Karte fast eine Sekunde dauern
kann.
Torsten
Datum:
Also selbst wenn ich das Timeout von 10 auf 1000 erhöh kommt immernoch 0x3f zurück.
Datum:
Angehängte Dateien:Hallo! Frage nebenher: Hat hier schonmal jemand den Datendurchsatz für einen SCHREIBvorgang getestet? Ich übertrage mit 38.400 baud (8N1) über uart eine binäre Datei. Das macht max. 3.840 Nutzbytes/s. Ohne auf die SD-Karte zu schreiben (im Quelltext, wenn MACHS_WIRKLICH nicht definiert ist) erreiche ich dieses Maximum auch tatsächlich fast. Bin ich maximal 1s drüber bei einer 64kB Datei. Wenn ich nun aber auf die Karte schreibe sinkt die Übertragungsrate auf aller höchstens 120 Byte/s. Wohlgemerkt Byte - keine kB! Eine 20kB Firmwaredatei braucht plötzlich über 3 Minuten. Dabei habe ich den Schreibpuffer (s. Quelltext) auf satte 512 Byte eingestellt. Habt ihr das Problem auch oder ist das normal, weil FAT aufwendig ist? Grüße!
Datum:
Mathias Schau Dir doch bitte einmal die Datei sd_raw.c vom sd-reader genauer an weil es sich in diesem Thread genau darum dreht ;) Ob ein Timeout von 1000 für eine Zeit von rund ~1s reicht wage ich stark zu bezweifeln. Das geht nur bei den AVR's weil man jeden Takt zählen kann und somit die Ausführungszeit vorhersagbar ist. Nur Vermutungen weil ich von dieser CPU/MPU noch nie etwas gehört habe: - der Code wird in einem Cache ausgeführt - der Compiler optimiert stark ... so das Deine Schleifen in einem 'Wimpernschlag' ausgeführt werden nicht aber in der Größenordnung die benötigt wird. Möglicherweise hat der Tricore einen Timer. Wenn ja, verwende besser diesen für einen Timeout. Torsten
Datum:
Hallo Roland,
ich habe deine Schaltung nachgebaut, allerdings mit Mega64 und meine
Kontrolle ober Karte gesteckt bzw schreibschutz liegen immer auf low, da
ich keinen Sockel habe.
Problem ist aber, dass sich die Karte nicht (richtig) initialisieren
lässt.
wenn ich die Karte n paar mal rausnehme und wieder reinstecke gehts mit
viel glück.
Habe das Problem verfolgt und hab dann herrausgefunden dass er mir in
der Funktion sd_raw_init da aussteigt:
/* reset card */
uint8_t response;
for(uint16_t i = 0; ; ++i)
{
response = sd_raw_send_command_r1(CMD_GO_IDLE_STATE, 0);
if(response == (1 << R1_IDLE_STATE))
break;
if(i == 0x1ff)
{
unselect_card();
return 0;
}
}
woran könnte das liegen? hab schon verschiedene Karten ausprobiert und
bei allen das selbe Syndrom.
Danke Stefan
Datum:
Hallo Stefan, stefan richter wrote: > [...] da ich keinen Sockel habe. > Was verwendest Du denn dann?? > Problem ist aber, dass sich die Karte nicht (richtig) initialisieren > lässt. - Welche Anbindung? - Stromversorgung per Wandler oder mit Dioden? - Extra Pegelwandler oder Spannungsteiler? Vor allem die letzten zwei Punkte sind kritisch. Wenn dann noch lange Kabel oder Selbstbau-Sockel dazukommen, kann es durchaus Probleme geben. Siehe dazu auch die Beiträge weiter oben im Thread. Gruß, Roland
Datum:
Hallo Stefan,
Habe auch mal das Filesystem von Roland auf einem Mega64 probiert.
Am Anfang hatte ich auch Probleme.
Eines davon war bei sd_raw_init:
/* card needs 74 cycles minimum to start up */
for(uint8_t i = 0; i < 10; ++i)
Bei mir wurden komischerweise nur 5 Datenpakete ausgegeben (gemessen).
Weiss der Geier, warum..
Nachdem ich es geändert hatte in
/* card needs 74 cycles minimum to start up */
for(uint8_t i = 0; i < 20; ++i)
lief es einwandfrei.
Es ist ja ein Minimumwert. Mehr 0xFF-Bytes zu senden, schadet nichts.
Wichtig ist auch, dass der SPI Takt bei Init nicht über 400KHz liegt.
Und selbstverständlich, dass der Chip-Select für die Karte richtig
angesteuert wird.
Roland:
Welchen maximalen Lesedurchsatz hast Du hinbekommen?
Ich habe nur max. 250KBytes/Sek. geschafft. Für 512 Bytes, was einem
Sektor entsprechen sollte:
/* load file contents for speed measurements */
uint8_t buffer[512];
while(fat16_read_file(fd, buffer, sizeof(buffer)) > 0)
{
}
Ich verwende keine SPI, sondern ein externes CPLD, welches eine SPI mit
25MBits/Sek. enthält. Der Datenaustausch erfolgt rein über
Speicherzugriffe und der Status der SPI wird über einen Portpin
abgefragt, z.B. Senden:
void sd_raw_send_byte(uint8_t b)
{
uint8_t *SDAddress;
uint16_t i;
if (Initcard == 1)
i = 0x1101; //write INIT Mode 400KBits/Sek.
else i = 0x1102; //write fast mode 25MBits/Sek.
SDAddress = (uint8_t *) i;
*SDAddress = b; //write Data
_asm__ __volatile_ ("nop"); //allow "Ready" to change
while (PIND & (1<<PIND0)) //wait for "Ready"
{
}
}
Dein Filesystem ist sehr komfortabel. Bin zwar noch nicht ganz
durchgestiegen, weil ich noch nicht solange in C programmiere, aber es
funzt. Was ich noch gerne machen würde, wäre den Zeichenvergleich für
den Dateinamenszugriff Case-unabhängig zu machen. So dass man beim
Konsolenbetrieb nicht immer exakt auf Groß/Kleinschreibung achten muss.
Bin aber noch nicht durch Deine Strukturen durchgestiegen, bzw. wie die
Eingabestrings mit den Dateinamen verglichen werden.
Auch will ich mal versuchen, komplette Sekoren oder gar Cluster komplett
einzulesen, ohne die ständigen Bereichsabfragen, die (so wie es
aussieht), das ganze ziemlich ausbremsen.
Aber sonst: Hohes Lob!
Joachim
Datum:
Joachim wrote: > Roland: > Welchen maximalen Lesedurchsatz hast Du hinbekommen? > Ich habe nur max. 250KBytes/Sek. geschafft. Für 512 Bytes, was einem > Sektor entsprechen sollte: > [...] Mit diesem Wert bist Du recht gut dran. Konkrete Messungen habe ich bei mir allerdings noch nicht gemacht. Mein SPI läuft mit 8MHz, schon daher dürfte der Durchsatz um ein Vielfaches geringer sein. Generell gilt, je größer die Blöcke sind, die Du auf einen Schlag liest, desto geringer ist der Overhead und desto schneller somit der Durchsatz. Versuch es, je nach RAM-Ausstattung Deines Controllers, also mal mit Blöcken von 1kB, 2kB oder mehr. > Was ich noch gerne machen würde, wäre den Zeichenvergleich für > den Dateinamenszugriff Case-unabhängig zu machen. So dass man beim > Konsolenbetrieb nicht immer exakt auf Groß/Kleinschreibung achten muss. > Bin aber noch nicht durch Deine Strukturen durchgestiegen, bzw. wie die > Eingabestrings mit den Dateinamen verglichen werden. Dazu ist es nicht unbedingt nötig, meinen Code zu ändern. Das kannst Du auf Applikationsebene machen, wenn Du alle Dateien entweder in Groß- oder in Kleinschreibung abspeicherst und alle Strings, die meinem FAT16-Layer übergeben werden, zuvor entsprechend in Groß- oder Kleinschreibung konvertierst. Das hätte auch den Vorteil, dass Du meinen Code leichter auf neuere Versionen aktualisieren kannst. > Auch will ich mal versuchen, komplette Sekoren oder gar Cluster > komplett einzulesen, ohne die ständigen Bereichsabfragen, die (so wie > es aussieht), das ganze ziemlich ausbremsen. Welche Abfragen genau? Die Dateien müssen in Cluster aufgeteilt werden, da diese über den Datenträger verstreut liegen können. Die Aufteilung in Sektoren (bzw. Blöcke) ergibt sich durch die Struktur der SD-Karten. Eine Beschleunigung kann man z.B. durch - Vergrößerung des Blockpuffers, - Zwischenpufferung der Verzeichniseinträge und - Zwischenpufferung der FAT erreichen. Das habe ich aber zwecks guter Einsetzbarkeit auf möglichst vielen verschiedenen Controllern und mangels RAM auf meinem mega168 nicht implementiert. Gruß, Roland
Datum:
hallöle, funzt der code auch mit sehr grossen speicherkarten (ca. 10 GB oder so)? sorry, aber ich wollt' mir nicht alle ~300 beiträge hier durchlesen...
Datum:
Hallo Peter, FAT16 unterstützt nur Partitionsgrößen bis 2GB, dies gilt daher auch für meinen Code. Unterstützt werden Medien bis 4GB, welche mit mindestens 2 Partitionen nutzbar sind. Gruß, Roland
Datum:
Angehängte Dateien:Hallo an alle, Nachdem ich von Torsten eine positive Rückmeldung für die Unterstützung der Modifikationszeit bekommen habe, hier ein neues Release. Die Änderungen im einzelnen: - Unterstützung für das Lesen und Setzen der Modifikationszeit neu angelegter oder geänderter Dateien und Ordner. - Bugfix für einen Fehler in sd_raw_read() bei Benutzung des Blockpuffers. Ab sofort stehen auf meiner Homepage auch Patches bereit, die nur die Änderungen seit des jeweils letzten Release enthalten. Diese sollten ein Update erleichtern, insbesondere wenn in der Zwischenzeit eigene Änderungen vorgenommen wurden. Viele Grüße, Roland
Datum:
Hallo! Hatte oben mal geschrieben, dass der Schreibdurchsatz sehr gering sei. Das wollte ich hiermit mal klar stellen ging auf meine Kappe. Hatte schon vor ein paar Wochen rausgefunden, dass ich den sizeof falsch verwendet habe und eine Puffergröße von 2 Bytes statt 512 hatte. Aber da sieht man mal, wie entscheidend diese Puffergröße ist. Vielen Dank für die Aufnahme meines Patches. Ist ja doch noch eine Menge Leben drin in den Routinen. Grüße!
Datum:
Hallo, ich suche die Original-CID und -CSD der SD-Karten Kingston Elite Pro 256MB Platinum 1GB Fragt mich nicht wie, aber mir ist es (unfreiwillig) gelungen, die read-only-Register CID und CSD dieser Karten kaputt zu bekommen. Bei der Kingston-Karte steckt eine halbe Kopie der CSD in dem CID- Register. Bei der Platinum-Karte stimmt die CRC7 bei CSD nicht. Was wieder eine ganze Reihe von Fragen aufwirft. ;-) Vielen Dank! August
Datum:
Hallo Roland, ich brauche für ein GPS-Fahrtenbuch Schreibzugriff auf eine MMC, also habe ich dein Projekt getestet: -Mega16 auf das STK500 gesteckt -Vtarget auf 3.3V konfiguriert -MMC Sockel mit einem Stück Flachbandkabel an PORTB angesteckt -Projekt kompiliert & geflasht -> Funktionierte auf Anhieb wunderbar! Wenn meine Platine da ist werde ich dann noch das NMEA Parsen & GPX schreiben (das Gerät soll direkt GPX Dateien auf die Karte schreiben) implementieren. Ich habe auf der Platine einen Goldcap mit 470.000 µF vorgesehen, mal sehen ob das reicht um die Daten noch gar auf die Karte zu schreiben wenn der Strom abgestellt wird... Also vielen Dank für das Projekt, Gruß Stefan
Datum:
Hi, hab folgendes problem mit dem Code sd_raw_init() partition_open() fat16_open() fat16_get_dir_entry_of_path() und fat16_open_dir() sind erfolgreich. Wenn ich dann aber fat16_create_file() oder fat16_create_dir() benutzen will, hängt er sich auf oder hat den Fehler, dass er keinen freien Clsuter findet. Die MMC wurde mit knoppix auf fat16 partitioniert (16 MB groß) und mit mkdosfs formatiert. Bin echt am verzweifeln, weil ich keinen logischen Grund finde... Grüße Christian
Datum:
hallo, ich hab grad laut anleitung von ulrich radigs webseite ein brotbrett bestueckt. http://www.ulrichradig.de/site/atmel/avr_mmcsd/gfx... der aufbau ist: ein stk500 mit atmega16 und 16MhZ quarz (laeuft). die +5V beziehe ich vom VTG anschluss an portB. sollten da beim mmc anschluss nach den 2 dioden nicht um die 3.7V zu messen sein? bei mir ist es davor: 4.96V und nach den 2 1N418 4.32V. jemand ne idee wo ich mich verbastelt haben koennte? mfg Hansl
Datum:
RTFM. Wenn du das Datenblatt gelesen hättest, wüsstest du, dass der Spannungsabfall vom Strom abhängig ist, der durch die Diode fliesst.
Datum:
@ jemand Genau. Die nächste Frage von Hansl kann man schon raten. Wieso funktioniert SPI mit den Spannungsteilern nicht bei 8MHz ;) Es ist doch immer wieder das gleiche leidige Thema :(
Datum:
holger: pack deine kristallkugel wieder ein und entspann dich. mcu ist geflasht. ausgabe am terminal is auch da. nun brauch ich nur noch irgendwo die mmckarte fat16 formatieren. mfg hansl
Datum:
SPI funktioniert bei mir sehr wohl mit den Spannungsteilern, auch bei 14,x MHz. Die 3,3V Spannungsversorgung mit der Diodenlösung dagegen nicht. Unbedingt, das wurde mehrfach erwähnt, einen eigenen Regler dafür verwenden. VORSICHT mit dem LM317 und einigen 3,3V Festspannungsreglern: Manche brauchen eine Mindestlast von einigen mA! Eine SD-Karte braucht nur Strom wenn darauf zugegriffen wird. Bei einem ungeeigneten Regler könnte die Spannung auf unzulässige Werte hochlaufen. Sehr gute Erfahrungen habe ich mit einem "LP 2950 CZ-3,3" gemacht. Meinen 5V-Regler (78L05) habe ich wegen der guten Erfahrungen durch einen "LP 2950 CZ-5,0" aus der gleichen Familie ersetzt. Ein feines Teil btw, der Ruhestrom liegt im µA Bereich. Das kann wichtig für Batterie-Betrieb sein: der Ruhestrom ist ca. 5mA geringer pro Regler. Beide gibt es für 60 Cent bei Segor. Torsten
Datum:
Hallo, torsten: danke, hab diese fehlerquelle mal enfernt. Hab nun anstelle der moeglicherweise wackeligen diodenloesung genau wie stefan ein paar posts weiter oben beschrieben hat die VTARGET konfigurationsmoeglichkeit des stk500 benutzt. Leider ist alles was in der console zu sehen ist dies hier: "MMC/SD initialization failed" jemand ne idee woranns liegen koennte? oder kommt die meldung auch wenn kein-oder ein ungueltiger partitiontable oder fat gefunden wurde? hier noch ein paar details zum setup: SPI ist enabled (0) die konfiguration der Anschluesse beim Atmega16: PORTB4(SS) - MMC CS *via spannungsteiler PORTB5(MOSI) - MMC DI *via spannungsteiler PORTB6(MISO) - MMC DO PORTB7(SCK) - MMC CLK *via spannungsteiler uisp -dprog=stk500 -dserial=/dev/ttyS0 -dspeed=115200 -dpart=atmega16 --rd_aref --rd_vtg --rd_fuses Firmware Version: 1.14 VTarget = 3.3 V ARef = 3.3 V Atmel AVR ATmega16 is found. Firmware Version: 1.14 Fuse Low Byte = 0xff Fuse High Byte = 0xd9 Cannot read extended fuse bits on this device. Returning 0xff Fuse Extended Byte = 0xff Calibration Byte = 0xbf -- Read Only Lock Bits = 0xff BLB12 -> 1 BLB11 -> 1 BLB02 -> 1 BLB01 -> 1 LB2 -> 1 LB1 -> 1 achja, die karte ist ne 128MB MMC - takeMS. die hab ich noch nie benutzt, weis also weder ob noch wenn womit die formatiert ist. mfg hansl
Datum:
> jemand ne idee woranns liegen koennte? oder kommt die meldung > auch wenn kein-oder ein ungueltiger partitiontable oder fat > gefunden wurde? Ähem - wenn Du die Sourcen durchlesen würdest, wüsstest Du, dass bei DIESER Meldung noch gar kein Partitionseintrag eingelesen wurde. Diese Meldung bezieht sich rein auf sd_raw_init(). Die Karte sendet also keine gültigen Response-Daten. Also zu 90% Hardware- oder Interface-Fehler. Musst halt mal anzeigen lassen, was die Karte überhaupt antwortet. Wenn sie denn überhaupt antwortet. NEUE Karten in der Größe <=2GB sollten ab Werk ausschließlich mit FAT16 formatiert sein. Ich habe noch niemals eine andere gesehen und schon ca. 300 Stück verschiedener Karten "verbaut". Vorsicht bei gebrauchten aus Ebay: Da wurde oft schon drauf rumgepfuscht. Wenn die Karte unter Windows neu formatiert wird, macht Windows in vielen Fällen FAT12 draus, wenn die Karte relativ klein ist (z.B. 64MB). Bei ersten Versuchen würde ich Billigkarten vermeiden. Manche haben ein Problem mit dem SPI-Modus, obwohl sie in Kameras oder Cardreadern problemlos laufen. Will hier keine Schleichwerbung machen, aber Karten von SanDisk oder Kingston waren bei mir immer problemlos. Zum Thema "Spannungsteiler mit Widerständen" wollte ich noch sagen, dass die allseits bekannte Schaltung bis 4MHz funktioniert. Bei meinem M16C Kontroller geht das sogar noch bei 8MHz SPI-Takt. Allerdings liefen manche Kartenfabrikate nicht, vor allem irgendwelcher Noname-schrott ala "extreme-memory". Billige Karten reagieren recht sensibel auf allzu "verwaschene" Signale. Sichere 8 MHz mit AVR erreicht man mit niederohmigeren Widerständen. Also nicht im Bereich 1,8/3,3 KOhm, sondern zum Beispiel 330/620 Ohm. Bedeutet natürlich eine höhere Strombelastung, aber die Flanken werden wieder steiler und somit ist eine höhere Frequenz möglich. Auf "wundersame" Weise funktionierten danach auch Karten, die sich vorher niemals haben ansprechen lassen ;-) Bei 12Mhz ist mit der Spannungsteilerlösung so ziemlich Schluss. Aber die werden mit einem AVR eh nicht erreicht. Wenns also billig sein muss und der AVR unbedingt an 5V laufen muss, dann funktioniert diese Lösung in jedem Fall. Mittlerweile arbeite ich mit ARM und da tritt das Problem glücklicherweise nicht mehr auf :-) Joachim
Datum:
joachim: danke fuer die ausfuehrungen. werd mal mit dem hardwareaufbau herumexperimentieren. den code hab ich mir natuerlich angesehen != verstanden. bei elm chans software blick ich leider noch weniger durch. mfg Hansl
Datum:
Hat noch jemand die ursprünglichen AtMega8 Sourcen für ein FAT Filesystem und kann er die Hier im Forum zur Verfügung stellen? Das Ganze soll als Basis für einen kompakten Datenlogger dienen. Schon im Voraus vielen Dank.
Datum:
Hansl: Jetzt muss ich aber nochmal fragen: Du hast die Versorgung des Boards auf 3,3V gesetzt und die Spannungsteiler dringelassen??? So interpretiere ich jedenfalls Dein vorletztes Posting. Joachim
Datum:
joachim: jepp, hab ich. nach ein wenig gruebeln war mir dann klar das das topfen ist :) und habs rausgenommen. mittlerweile hab ich die MMC karte bei nem freund getestet und es hat sich herausgestellt das weder dessen cardreader noch sein palm pilot mit dem ding was anzufangen weiss. der palm meldet eine fehlerhafte karte, der windoofpc aeussert sich nicht dazu. hab heute um 5 euronen ne 128mb RS-MMC karte von Lexar, was auch immer RS sein soll, gekauft und nen LT1086 CM-3.3 von nem fibrechanneladapter gebrutzelt. werde des naechtesns wenns klima wieder passt einen 2. versuch starten :) dann wieder mit spannungsteiler am SPI und 5V VTARGET. mfg Hansl
Datum:
es ist verhext. immer noch die MMC/SD initialization failed fehlermeldung :( elektrisch sollte alles korrekt sein. mmc wird durch nen LT1086 CM-3.3 versorgt. habs nun mal mit 330 und 650 Ohm widerstaneden als spannungsteiler probiert aendert auch nichts. gestern hat die karte in nem cardreader aufjedenfall einwandfrei funktioniert. also wenn ich die karte nciht irgendwie beim aufbauen geschrottet hab sollte die nun funktionieren. folgendes habe ich messen koennen(mieses multimeter): CS (MMC PIN1, MCU PB4) 3.24V DATA IN (MMC PIN2, MCU PB5) 3.24V VCC (MMC PIN4) 3.27V DATA OUT (MMC PIN7, MCU PB6) 4.74V hab keinen schimmer woranns liegen koennte :( achja, ISP kabel abziehen bringt auch nix. weitere debuggingtips? mfg Hansl
Datum:
Hast du einen 100nF C über die 3,3V direkt am Kartenslot?
Bei mir läuft seit fast zwei Jahren die folgende Beschaltung.
Der interne PULL-UP am MISO ist deaktiviert
Für Signale vom uC an die Karte (CS, MOSI, SCK)
3v3 ^
|
| |
| | 47k
| | 2k2
| _____
MMC/SD -----O-----_______------ uC (out)
|
| |
| | 3k9
| |
|
GND
Data-Out der Karte (MISO)
3v3 ^
|
| |
| | 47k
| | 330
| _____
MMC/SD -----O-----_______------ uC (MISO)
Datum:
werner: hab nun auch deine schaltung aufgebaut, und in Rolandscode noch ein PORTB &= ~_BV(PB6); ergaenzt um den pullup des MISO PORTS zu deaktivieren. ergebnis unveraendert. ich vermute das irgendwo am stk500 der hund begraben liegt... nur wo? dies ist nun der dritte aufbau. diesmal sogar mit 8Mhz internem takt! und 100nf C am mmc. sicher ist sicher :) anbei nochmal meine aktuellen fusesettings: Fuse Low Byte = 0xd4 Fuse High Byte = 0xd9 Atmega16 @ 8MhZ, JTAG DISABLED die mmckarte funktioniert. aufjedenfall hab ich das dintg gestern nochmal getestet. leider aber nur mit einem palm :( jemand irgendeine idee? ich tippe auf das stk500, denn das ist das einzige an dem ich ausgenommen von "spi-programmingkabel trennen" nix geaendert habe.. mfg Hansl aus dem, hey das guck ich mir schnell mal an ist mittlerweile ein jahresziel geworden ;)
Datum:
Tips hast Du bekommen, nur ob Du die umsetzt, ist fraglich. Beim Lesen Deiner Beschreibungen kommt es einem so vor, als ob Du "wahllos drin rumstocherst". 1. Besorg Dir ein Oszi und mess die SPI Leitungen. Gib dazu ein Muster an SPI aus z.B. 0x5A und schau Dir die Signale SCLK und Data direkt an der SD Karte an. Messe auch den Chip select. Denk dran: Im Initmode darf die SD Karte maximal 400KHz bekommen. Multimeter kasste vergessen. Man kann Hardware solange "blind" programmieren, wie man Glück hat, dass alles klappt. Wenn aber der Wurm drin ist, kommt man ohne das richtige Messzeug nicht weiter. Wenn Du gar keine Chance hast, ein Oszi zu bekommen, dann bastel Dir eine verbindung zwischen den Anschlüssen Data In und Data Out der SD-Karte (natürlich solange diese NICHT eingesteckt ist :-) und mach einen Loopback-test der SPI-Schnittstelle. Also ob das Byte, welches Du sendest auch wieder reinkommt. 2. Gebe nach JEDEM Schritt ALLE empfangenen Daten der SD-Karte auf Dein Terminal aus. Wenn gar nichts kommt, dann erzeuge zusätzliche Hilfsmeldungen und sieh nach, WO in den Funktionen ein Timeout erfolgt. Roland hat ja schon die UART implementiert, also wo ist das Problem? Es geht nur Schritt für Schritt. Und immer nur EINE Sache ändern bzw. testen, niemals MEHRERE gleichzeitig. Das ist extrem wichtig. Und um Himmels Willen - besorg Dir irgendein billiges Oszi ;-) Joachim
Datum:
joachim: zu 1: oszi hab ich keins, kenn niemanden mit einem und kann ich mir auch dieses jahr wohl sicher keines leisten. loopbacktest, klingt einleuchtend, mal sehn ob ich dazu code finden kann. zu 2: das mit dem code aendern ist ja nicht so einfach wenn man nicht versteht was da genau passiert. vorallem besteht bei mir eher die gefahr das der code wenn ich drinn ein wenig rumruehre ploetzlich nichtmehr tut und dann faengt das "wahllos herumstochern" erst an. ein paar printfs in "uint8_t sd_raw_init()" waern schon praktisch. mal gucken wie ich das angehen koennte. das Jahr ist ja noch lang :) hab wohl immer eine sache geaendert :) mal die widerstaende ausgetauscht. dann mal den takt geaendert, dann mal nen kondensator dazu, dann mal ne neue MMC karte ran.....worauf willst DU HINAUS? (caps konnt ich mir ned verkneifen ;)) mfg Hansl
Datum:
> loopbacktest, klingt einleuchtend, mal sehn ob ich dazu code finden > kann. Wirst Du kaum. Musst Du selber programmieren. Aber es gibt sicher irgendwo Basisroutinen zum Schreiben und Lesen eines Wertes an/von SPI. Um möglichst die originale Initialisierungssequenz zu nehmen, müsstest Du den Loopbacktest hier einfügen (in der Main.c): /* setup sd card slot */ if(!sd_raw_init()) { #if DEBUG uart_puts_p(PSTR("MMC/SD initialization failed\n")); #endif // HIER DEN LOOPBACK TEST return 1; } Da beim betrieb ohne Karte und gebrücktem DIN/DOUT die Fehlermeldung natürlich vorprogrammiert ist, muss der Test genau hinter der Fehlermeldung rein. Der Vorteil: Du kannst die vorhandene SPI-Init nehmen. > das mit dem code aendern ist ja nicht so einfach wenn man nicht > versteht was da genau passiert. Du sollst ja nicht sehr viel ändern, sondern nur ergänzen! Der Trugschluss bei solchen Fremdprojekten ist, dass man sich die Arbeit sparen kann. Das geht, wenn man Glück hat und alles funktioniert (was in den seltensten Fällen so ist). Wenn man aber hängt, braucht man viel Zeit, durchzusteigen. Da solche Projekte meist schon sehr weit gediehen und optimiert sind, und mit allen möglichen Features ausgestattet, ist es sehr schwer, die relevanten Punkte herauszulesen. Man braucht oft lange, herauszufinden, WO WAS und WARUM definiert ist. Geht mir auch nicht anders. Da muss man durch. Ich mache es aber so: Wenn etwas absolut nicht laufen will, dann schreibe ich mir erstmal ein paar eigene Testprogramme für die Hardware. Erst wenn diese erfolgreich verlaufen, kehre ich wieder zum Projekt zurück. Ich würde vorschlagen, Du vergisst erst mal die Sd-Karte und beginnst damit, die SPI-Schnittstelle selber mal zu programmieren (einen besagten Loopbacktest zu schreiben). Wenn das dann funktioniert, kannst Du wieder zur SD-Karte zurückkehren. Joachim
Datum:
Angehängte Dateien:Hallo, hab nun ein wenig herumkopiert und sende nun 0XFE als testwert. scheine es aber nie zu empfangen. hab ich da einen offensichtlichen fehler drinne? oder ist meine hw total hinueber? mfg Hansl anbei das gaenderte main.c aus sd-reader_source_20070603 dabei handelt sichs eiegentlich nur um einwenig copy&paste aus sd_raw.c.
Datum:
zur hardware... hab einfach mosi und miso verbunden. ansonst, alles beim alten, atmega16@8Mhz(interner taktgeber), stk500 fuses:Fuse Low Byte = 0xd4, Fuse High Byte = 0xd9 mfg Hansl
Datum:
ok, klappt doch,
hab vergessen das ueberfluessige zeug auszukommentieren :)
nungut. also spi funktioniert also grundsaetzlich.
aendeurng in main.c von zuvor:
uint8_t sd_raw_rec_byte()
{
/* send dummy data for receiving some */
// SPDR = 0xff;
// while(!(SPSR & (1 << SPIF)));
// SPSR &= ~(1 << SPIF);
return SPDR;
}
mfg
Hansl
Datum:
> hab vergessen das ueberfluessige zeug auszukommentieren
Ahaaa ;-)
Na also, nachdem Deine SPI nun sendet und empfängt, musst Du sehen, ob
das Chipselect signal für die Karte anliegt.
Das kann man leider nicht simulieren sondern nur messen.
Checke auch, ob Du den richtigen Port für das Selectsignal eingestellt
hast.
Das Select ist definiert in der sd_raw_config.h für die verschiedenen
Kontrollertypen:
#define select_card() PORTB &= ~(1 << xxxx)
#define unselect_card() PORTB |= (1 << xxxx)
Desweiteren würde ich für den Anfang die hohe Taktrate für die SPI
abschalten und folgende Zeilen auskommentieren (in sd_raw_init() in der
sd_raw.c). Das kannst Du gleich tun. Es beeinflusst die Gesamtfunktion
nicht, schützt Dich aber vor weiteren möglichen Hardwareproblemen.
/* switch to highest SPI frequency possible */
SPCR &= ~((1 << SPR1) | (1 << SPR0)); /* Clock Frequency: f_OSC / 4
*/
SPSR |= (1 << SPI2X); /* Doubled Clock Frequency: f_OSC / 2 */
Erst wenn die Karte komplett läuft, gibst Du dies wieder frei.
Läuft die Karte DANN nicht mehr, kannst Du sicher sein, dass Dein
Interface den hohen Takt nicht veträgt und die Signale "verwaschen".
Tja - viel mehr fällt mir dann auch nicht mehr ein.
Joachim
Datum:
Immer noch kein Licht am Ende des Tunnels :( Hab nun fogendes Setup: STK500 auf 3.3V konfiguriert, Atmega16 @ 8MhZ, JTAG deaktiviert ISP KABEL abgesteckt! Hardwaresetup: PORTB4 ------- CARDSELECT, PIN1 (gemessen 3.3V) PORTB5 ------- DATAOUT, PIN7 PORTB6 ------- DATAIN, PIN2 PORTB7 ------- CLOCK, PIN5 VTG ---------- VCC, PIN4 (gemessen 3.3V) GND ---------- GND, PIN3 & PIN6 Software anbei. (Mit den von Jochaim empfohlenen Aenderungen) falls irgendjemand noch ne idee hat worans liegen koennte...bitte schreien! werd mir falls da nix mehr zu debuggen geht wohl oder uebel ne platine aetzen und das ganze mal ohne stk500 probieren. mfg Hansl
Datum:
Du weiss aber schon, dass bei dem Projekt 2 weitere Leitungen verwendet werden, mit denen die GESTECKTE Karte (SD_available) und der SCHREIBSCHUTZ (SD_Locked) abgefragt werden? Der Schreibschutz ist erstmal unnötig. In der sd_raw_config.h ist der Port fürs Erkennen der Karte definiert:
#define configure_pin_available() DDRC &= ~(1 << DDC4) #define get_pin_available() ((PINC >> PC4) & 0x01) |
In der sd_raw.c wird dies überall abgefragt. Die Funktion dazu:
* \ingroup sd_raw * Checks wether a memory card is located in the slot. * \returns 1 if the card is available, 0 if it is not. */ uint8_t sd_raw_available() { return get_pin_available() == 0x00; } |
Ich habe die bei mir geändert, weil ich auch keine Kartenerkennung benutze und dies zur Fehlermeldung geführt hätte:
uint8_t sd_raw_available()
{
return 1; //get_pin_available() == 0x00;
}
|
Probier das mal. Leider hast Du die konkrete Verdrahtung der Karte erst jetzt gepostet, sonst wäre mir das schon eher aufgefallen. Joachim
Datum:
joachim: noe hatte ich tatsaechlich uebersehn. hab deine vorschlage alle ausprobiert. der hund ist leider immer noch drinn. die lexar karte funtioniert hier garnicht. eine 32mb nonamekarte eines freundes ergibt alle heiligen zeiten mal die meldung "opening partition failed". (power on, power off, power on, reset, reset....in irgendeiner reihenfolge und so oft man lust dazu hat) allerdings nur dann wenn ich PORTB &= ~_BV(PB6); also den internen pullup des MISO aktiviert habe. wenn ich das rausnehme bekomme ich die klassische..NIX DRANN meldung. ich werd wohl wie geplant demnaechst ne platine aetzen und das stk500 als fehlerquelle eliminieren. mfg hansl
Datum:
Tja, dann bin ich auch am Ende meiner Weisheit. Sorry. Joachim
Datum:
Sehe ich das richtig? Ist die Standard Port-Belegung genau so wie bei dem ISA-Ctrl Webserver? Kann ich das so auf der Platine nutzen ohne irgendwelche Änderungen?
Datum:
@roland riegel hi ich habe dein testprogramm kompiliert und auf einen ATMega128 geschrieben. Ich kann damit auf anhieb eine 64 MMC karte auf anhieb ansprechen, beschreiben und lesen. Ich danke dir für so ein tolles programm, jetzt muss ich mir es nurnoch genauer angucken und verstehen. Testbedingungen: ATMega128 mit 6MHz, noname 64 MB MMC an Hardware-SPI
Datum:
Ich verwende Rolands (Danke!) Code als Basis für eine eigene extrem resourcengeizige MMC/SD-Anbindung an einen Mega8. Die MMC-Karten sind noch unterwegs, in der Zwischenzeit habe ich mit Transcend 1GB miniSDcards (lagen noch von einem anderen Projekt herum) angefangen. Folgende Zugriffe auf die Karte funktionieren: Init (modifiziert, nun ohne sd_raw_available und CMD_SET_BLOCKLEN==16) / CMD_SEND_CID/CMD_SEND_CSD. Folgende Probleme treten auf 1) Single-Block Lesezugriff funktioniert auf volle Sektorvielfache (512byte). Bei Blockzugriffen auf Startadressen die nicht & ~0x1FF sind hängt sich die Karte auf, keine Fehlermeldung. 2) die Adressierung auf der Karte hat einen Offset von 0x1FE00. D.h. der MBR erscheint bei 0x1FE00, der Rest ist entsprechend verschoben, aber sektorweise korrekt lesbar. In der SanDisk MMC Doku habe ich auf dieses Verhalten keinen Hinweis gefunden, die Karte kann laut CSD bit79 partielle Zugriffe (READ_BL_PARTIAL). Frage: hat jemand eine Idee ob das mit dem Offset an der SD liegt? Ich benötige die partiellen Zugriffe, um mit ganz weng SRAM schnell ein paar Bytes zu bekommen (waveform von SPI-MMC abspielen, über SPI-DAC, 22050kHz Samplerate).
Datum:
> ..und CMD_SET_BLOCKLEN==16) Wo gibts das? Ich sehe nur: #define CMD_SET_BLOCKLEN 0x10 und das bedeutet nichts anderes, als dass der Kommandocode für SET_BLOCKLEN 0x10 (CMD16) ist. Und das schmeisst Du raus??? > 1) Single-Block Lesezugriff funktioniert auf volle Sektorvielfache > (512byte). Bei Blockzugriffen auf Startadressen die nicht & ~0x1FF sind > hängt sich die Karte auf, keine Fehlermeldung. Es sind gemäß Grundeinstellung keine Lesezugriffe kleiner als 512 Bytes erlaubt. Siehe:
/* set block size to 512 bytes */ if(sd_raw_send_command_r1(CMD_SET_BLOCKLEN, 512)) |
Wenn Du die Startadresse nicht auf den Sektorstart legst, jedoch eine
Blockgröße von 512 eingestellt ist, kommt es zu einem Sektorüberlauf
(Read Block Misalignment).
> Frage: hat jemand eine Idee ob das mit dem Offset an der SD liegt?
Nein.
Der Offset ist eine Eigenschaft des FAT-Filesystems.
Der MBR liegt nie gleich am Anfang der Karte.
In der Partitionstabelle ist der Offset angegeben, z.B.
"Sectors preceding partition 1: 237"
Der MBR liegt also in diesem Fall bei 0x1DA00
Joachim
Datum:
Angehängte Dateien:Hi ich habe mal eine kleine zusammenfassung geschrieben für Roland Riegels MMC/SD FAT16 code. hoffendlich hat Roland Riegel nichts dagegen. und vieleicht hilf das ja einen weiter.
Datum:
Hallo, ich verwende Rolands Code auf einem ATmega32 und möchte sehr viele Daten in vielen Dateien auf einer MMC schreiben - möglichst schnell. Ich habe eine Testroutine erzeugt, welche 1000 Dateien mit der Größe 1kB erzeugt, alle im Root-Verzeichnis. Zum Debuggen lasse ich mit ausfühliche Infos per UART zum PC senden. Mir ist aufgefallen, dass schon nach ein paar Dateien das Erstellen und Öffnen der Dateien sehr lange (1 bis 5 Sekunden) Dauert. Ist das normal? Kann man das ganze beschleunigen? Würde es schneller gehen, wenn man Unterordner anlegt und darin die Datei schreibt? michi
Datum:
>Ich habe eine Testroutine erzeugt, welche 1000 Dateien mit der Größe 1kB >erzeugt, alle im Root-Verzeichnis. Bei FAT12 und FAT16 kann man maximal 512 Dateien im RootDir anlegen. Wenn sie nur 8.3 DOS Dateinamen haben jedenfalls. Mit langen Dateinamen sind es höchstens noch die Hälfte. Eher weniger. Wenn du 1000 Dateien anlegen willst musst du ein Unterverzeichnis anlegen und dort die Dateien schreiben.
Datum:
Das mit den 512 Dateien ist klar, aber die Geschwindigkeit wurde schon nach 50 bid 80 Dateien im Root-Verzeichnis beachtlich langsam. Wo müsste man denn ansetzen um den Code von Roland zu optimieren?
Datum:
Ich habe mehrere tausend Messungen mit unterschiedlichen Datensätzen und Längen. Diese sollen direkt weiter verarbeitet werden können, ohne den Umweg über ein Tool, was eine große Datei erst wieder auseinander nehmen muss. Eventuell erstelle ich schon vorher leere Dateien und lasse sie geöffnet. Das sollte doch problemlos möglich sein, auch wenn der Controller zwischendurch im Powerdown-Mode und die Karte ausgeschaltet wird oder?
Datum:
>Eventuell erstelle ich schon vorher leere Dateien und lasse sie >geöffnet. Wo merkst du dir für ein paar tausend offene Dateien z.B. den Startcluster ? Der ist mindestens 16 Bit. Bei 1000 Dateien brauchst du also schon mal min. 2kB RAM. Dann musst du dir noch merken an welcher Dateiposition du bei jeder Datei bist. Pro Position 32 Bit. Bei 1000 Dateien noch mal 4kB. Das war aber noch nicht alles was du dir merken musst :( Dein Konzept ist nicht realisierbar.
Datum:
>Wo merkst du dir für ein paar tausend offene Dateien z.B. >den Startcluster ? Der ist mindestens 16 Bit. Bei 1000 >Dateien brauchst du also schon mal min. 2kB RAM. Dann musst du dir >noch merken an welcher Dateiposition du bei jeder Datei bist. >Pro Position 32 Bit. Bei 1000 Dateien noch mal 4kB. > >Das war aber noch nicht alles was du dir merken musst :( >Dein Konzept ist nicht realisierbar. Doch, es sind nur ca. 10 Dateien gleichzeitig offen, eben 10 für jede Messung. Es werden pro Messung also 10 Dateien erstellt und es gibt später einige 1000 Messungen. Ich hatte mich etwas unglücklich ausgedrückt, sorry. Blöderweise bekomme ich sehr viele Daten in kurzer Zeit, so dass ich für jede geöffnete einen Buffer von min. 512 Byte brauche, damit es überhaupt mit dem Schreiben voran geht. Bei 4kB geht aber auch das nicht.... ich brauch ein neues Konzept. Aber nebenbei mal: Rolands Code ist wirklich klasse!
Datum:
Hello! I hope that it is OK to post questions in English. I have a Atmega16 and STK500 evaluation board, using the software generated clock at 3.68Mhz, all is operating at 5V. I haved used Rolands hardware connections and source code for interfacing SD card. UART working fine, but it is not possible to get any SD card to be accepted. 3 different types of SD cards has been tested, Toshiba 16MB, Kingston 1GB and RiData 512MB. The code is stopped at different positions depending on which card is used. 16MB cards is stopped when setting the block size to 512b, 512MB card stops after the verifing the FAT parameters, data_cluster_count is always larger than 65525. 1GB card stops in this loop
while(sd_raw_rec_byte() != 0xfe) |
located in SD_RAW.C anyonelse got similar problems? I think the problem for this is the partition table or what do you think?, I have used FDISK to create partitions for "06 FAT16" should it be primary or logic? and then format it in which way? Regards Niklas
Datum:
Hallo, hab das Filesystem in den Griff, hab nur probleme mit dem Stromverbrauch. Wenn die Karte in den Schacht geschoben wird ist alles ok. Jetzt wird die SD Karte initialisiert, beschrieben, gelesen, usw. Dafür brauche ich so ca. 40 mA, alles ok. Nachdem allerdings alle Vorgänge beendet sind, bleibt der Stromverbrauch bestehen. Gibt es einen Befehl, eine Möglichkeit, die SD Karte zurück in den Standby Modus zu bringen ?
Datum:
IIRC geht nach Spezifikation jede SD Karte nach einiger Zeit der Inaktivität automatisch in den Standby. Man muss nur den Chip-Select wegnehmen (und den Takt?). Eventuell liest du die Karte nicht vollständig aus (Dummy-CRC etc.) Ich schicke der SD Karte in meinen Programmen am Ende immer noch ein Dummy-0xFF, nehme den Chipselect weg und schicke noch ein 0xFF um der Karte einen Takt zum "Runterfahren" zu geben.
Datum:
Hallo, Super Projekt!!! ist es irgendwie möglich das es auch auf nem Atmega8 Funktioniert? Gruß Robert
Datum:
@ Niklas Eriksson, I got similar problems, I use a different Compiler (CrossStudio for AVR) I made some wrong settings (Datastacksize - was too small, and I used some Compiler-Optimization (10 hours of my life 4 nothing :-) )) best regards KL
Datum:
I used the roland-riegel sd/mmc AVR source with atmel128, 16 Mhz. (version 2007.01.20) http://www.roland-riegel.de/sd-reader/index.html It is good 512Mb SD/MMC cards, but 64 Mb and 128Mb is bad. Why? best regards Istvan Tiszai from Budapest
Datum:
Hallo, bin neu hier. Habe ein SD-Projekt welches seid jahren läuft. Jetzt tritt bei einem neuen Typ SD-Card (256MB PLATINUM) das Problem auf das beim lesen eines Blocks (Sektors Byte 0-511 +2CRC) an Stelle Byte5 immer die 0x04 gelesen und beim lesen vom MBR an Stelle Byte4 0x0F im Root bei Byte4 die 0x3F und im Bootsektor bei Byte4 die 0x5F gelesen werden. Das ist mit allen Karten diesen typs so. Mit Cardreader gelesen ist aber alles ok. Bei anderen Karten wie EXTREMEMORY habe ich das Problem nicht! Hat jemand ne Ide??
Datum:
Es kann am SPI-Signal selbst liegen. Manche Karten reagieren empfindlicher auf langsame Flanken. Ich hatte so ein Problem auch bei einer Serie von SanDisk Karten. Die waren (mit dem Spannungsteileraufbau) nicht zu gebrauchen. Bei einem neuen Design mit 3,3V Logik (steile Flanken) funktionierten die plötzlich auch. Bei hoher Taktrate kann es passieren, dass die Pegel nicht mehr ganz auf VCC bzw. GND gehen, sondern irgendwo "in der Luft hängen". Manche Karten vetragen das besser als andere. Ich würde mir mal die SPI-Signale anschauen. Wenn die "verwaschen" sind, die Widerstandswerte für den Spannungsteilen reduzieren. Dann werden die Flanken steiler und es könnte wieder klappen. Joachim
Datum:
Hallo Roland, Habe Dein Programm getestet. Erste Erfahrugen waren ausreichend, grösseren Dateien zu SCHREIBEN ist es aber wahnsinnig langsam. (Habe beim Schreiben eines Datenblock zum UART ein '.' gesendet. :))) ) Mit 1Mbyte Dateigrösse geht es so: am Anfang laufen die Punkte blitzschnell, am Ende kommen nur "Schrittweise". Eine Datei von 50-100kByte geht es in ca. 10 Sekunden, 1Mbyte zu schreiben dauert aber ca. 4(!) Minuten! Das ist gar nicht linear (u. akzeptabel). Habe ein bisschen im Programm nachgeforscht, es sieht so, dass bei der Clusterallokation ist was irgendwie zu langsam. Oder? Kannst Du mir was dazu sagen? Vielen Dank, Karoly
Datum:
Hallo Leute Wie kann man 2 Dateien gleichzeitig öffnen? Danke und Gruss So geht es nicht....
struct fat16_file_struct* fd1 = open_file_in_dir(fs, dd, "temp.txt"); if(!fd1) { uart_puts_p(PSTR("error opening1 ")); } //search file in current directory and open it struct fat16_file_struct* fd2 = open_file_in_dir(fs, dd, "temp2.txt"); if(!fd2) { uart_puts_p(PSTR("error opening2 ")); } |
Datum:
Muss ich etwa 2 Partitionen machen und jedes File aus einer anderen Partionion auslesen? (geht doch sicherlich auch noch einfacher)
Datum:
Hallo, Kurz gesagt: RTFM! In fat16_config.h: #define FAT16_FILE_COUNT 2 Gruß, Roland
Datum:
Hallo, auch ich bin derzeit ein wenig am probieren. Grundsätzlich funktioniert auch alles (eher selten bei mir) - solange es in der Hauptschleife läuft (main). Jetzt wollte ich mir ein paar Funktionen anlegen, um etwas Struktur in den Code zu bringen. Bis jetzt ist es mir nicht gelungen, die Dateioperationen, in einer Funktion zum Laufen zu bewegen. Ausgehend vom beiliegend Beispiel main.c -> sd-reader.hex habe ich den Part print_disk_info(fs) in eine Funktion geschrieben und selbige im main auskommentiert. Original:
int main() {... /* print some card information as a boot message */ print_disk_info(fs); ...} |
Versuch:
void test(void); int main() {... /* print some card information as a boot message */ //print_disk_info(fs); test(); ...} void test() { print_disk_info(fs); } |
Hoffe, es ist einigermaßen verständlich. Als Fehlermeldung erhalte ich : error: 'fs' undeclared (first use in this function) Im Moment trete ich auf der Stelle und weiß nicht so recht, wo ich ansetzen kann/soll. Viele Grüße Stephan
Datum:
Hallo Stephan! Schaue bitte in jedes beliebige Buch oder Online-Tutorial, welches eine Einführung in C liefert. In Deinem Fall ist da insbesondere der Abschnitt über den Gültigkeitsbereich von Variablen interessant. Die Fehlermeldung des Compilers sagt eigentlich schon alles. Kurz gesagt: Die Variable fs, die Du der Funktion print_disk_info() übergibst, muss in der aufrufenden Funktion test() oder zumindest im globalen Gültigkeitsbereich auch existieren. Gruß, Roland
Datum:
Hallo Roland, Kónntest Du bitte evtl. meine Frage auch beantworten? (Siehe 20.11.2007 09:33) Danke, Karoly
Datum:
Hallo Karoly! Nun, FAT16 ist insgesamt relativ ineffizient, vor allem mit wenig Pufferspeicher. Das nur vorweg. Ansonsten solltest Du bzgl. meines Codes auf mehrere Dinge achten: - SD_RAW_WRITE_BUFFERING unbedingt auf 1 stellen. - Wenn reichlich RAM bereitsteht, den Schreib-/Lesepuffer vergrößern (nur mit manuellen Codeänderungen möglich). - Der Datenblock, der fat16_write_file() übergeben wird, sollte möglichst groß sein. - Statt immer an das Ende der Datei zu schreiben, zu Beginn fat16_resize_file() aufrufen, danach ab Position 0 die Datei füllen. Das sollte die abwechselnden Schreibzugriffe auf die FAT, die Datei-Cluster sowie den Verzeichniseintrag unterbinden, so dass SD_RAW_WRITE_BUFFERING wesentlich besser greifen kann. So, ich denke das sollte Dir erst mal weiterhelfen. Gruß, Roland
Datum:
Hallo, ich versuche mich auch gerade bei der SD-Ansteuerung an einen ATmega324P. Als Levelshifter dient der MAX3378E, die 3.3V liefert ein extra Spannungsregler. Bei der SD Karte handelt es sich um eine SanDisk 1GB Standard (Rd/Rw: 3MB/s) Die Funktion sd_raw_init() funktioniert fehlerfrei, es wird jedoch nicht das Filesystem (FAT16) der SD-Karte erkannt. Nach dem Einlesen des FAT16 Headers springt er zurück, da sectors_per_fat = 0. Nun habe ich schon vielerlei Formatierungen ausprobiert, über die Datenträgerverwaltung (Format mit "FAT") und mkdosfs sowie eine Low-Level-Formatierung mit dem Panasonic SD Formatter und anschließender Windows-Formatierung. Auslesen der SD Karte mit WinHex zeigte, dass in allen Fällen ein FAT16-System erfolgreich angelegt wurde. Nur der Controller will dies nicht so recht glauben. Noch etwas: Lasse ich alle Initalisierungsroutinen in der Endlosschleife laufen, erkennt er im zweiten Durchlauf auch nicht mehr die Partition. Direkt nach dem Controllerreset versucht er zumindest, das Filesystem zu öffnen. Woran kann das liegen? Danke im Voraus Gruß Micha
Datum:
Ich habe mich letzte Nacht auch mit dem Anschluß von SD-Karten bespasst, daher sind meine Erfahrungswerte noch recht frisch ;) sectors_per_fat = 0 konnte ich dadurch beheben, daß ich erst die Partition -1 versuche und dann 0 - in umgekehrter Reihenfolge zu dem Beispiel-main.c Das Problem mit den mehreren Durchläufen hatte ich auch. Du mußt die verschiedenen Pointer wieder freigeben (partition_close, fat16_close etc.), dann klappt es auch mit den mehrfachen Durchläufen. Gruß, Kai
Datum:
Hallo Kai, danke für deine schnelle Hilfe, mein Initialisierungsproblem ist auch fast gelöst. Tatsächlich lässt sich Partition 0 nicht öffnen, folglich versucht er Partition -1 (Originalcode), was dann auch klappt. Danach lässt sich jedoch nicht das Filesystem öffnen. Lasse ich jedoch die Initalisierung erneut ablaufen (nach Pointerfreigabe, also partition_close() und fat16_close()) liest er plötzlich Partition 0 erfolgreich und erkennt auch ein FAT16 Dateisystem! Was ist denn nun passiert? Kehre ich die Partitionsreihenfolge um, wie du vorgeschlagen hast, öffnet er das FAT16 nicht (nicht mal nach mehreren Durchläufen). Gruß Micha
Datum:
Einige Anmerkungen: Partition -1 zu öffnen klappt immer. Das liegt aber daran, dass er die Karte in diesem Fall als Superfloppy (d.h. als einziger Datenbereich ohne Partitionstabelle) behandelt und deshalb auch keine Überprüfungen bzgl. der Existenz der Partition machen kann. Es ist also kein Zeichen von "Erfolg", wenn Partition -1 geöffnet werden kann. Auf dieser ein Dateisystem zu öffnen klappt aber hingegen nur, wenn die Karte auch wirklich als Superfloppy formatiert ist. Wenn also schon das Öffnen der Partition 0 scheitert, liegt dies nur an der Partitionstabelle, entweder weil die Partition nicht existiert, die Partitionstabelle fehlerhaft ist oder diese nicht existiert. Unter Linux klappt die Formatierung einer Karte so: 1. Karte einlegen. 2. Im Syslog nachschauen, unter welchem Namen sie eingebunden wurde. Annahme für die weiteren Schritte: /dev/sdc. 3. fdisk /dev/sdc o (Partitionstabelle löschen) n (neue Partition) p (primäre Partition) 1 (<-- eine Eins; erster Eintrag in Partitionstabelle) <Enter> <Enter> (Partition über gesamte Karte) t (Partitionstyp ändern) 6 (Typ: FAT16) p (Partitionierung ausgeben; überprüfen!) w (Partitionstabelle schreiben) 4. mkdosfs -F 16 /dev/sdc1 (<-- auf die Eins am Ende achten) Windows erzeugt meines Wissens nach eine Superfloppy. Grüße, Roland
Datum:
> Windows erzeugt meines Wissens nach eine Superfloppy.
Nee, macht auch ne Partition.
Joachim
Datum:
@Roland: Danke für die Hilfe, ich werde es unbedingt austesten! Karoly
Datum:
Ich habe gestern auf jeden Fall meinen Code derart erweitert, daß ich erst Partition 0 öffne und versuche auf das FAT16 zuzugreifen. Schlägt dies fehl, dann close ich Partition 0 und versuche es mit Partition -1. Erst wenn dies fehlschlägt, dann gibt es einen Fehler. Damit konnte ich erfolgreich alle (10 verschiedene) SD-Karten, derer ich habhaft werden konnte und die auf verschiedenen Geräten/OSen formatiert wurden, lesen. Ich habe aber noch ein paar Modifikationen an Roland's Code durchgeführt : - Software SPI - umschaltbar HW SPI / SoftSPI per #define im Header-File - An ein paar Stellen while (result = 0xfe); ersetzt durch eine Schleife, welche ein definiertes Ende hat - FAT32-Support angefangen zu implementieren (auch Header-File Option) Werde Roland mal einen Patch zukommen lassen - mal sehen, ob er die Änderungen gebrauchen kann.
Datum:
Hallo Kai, > Ich habe gestern auf jeden Fall meinen Code derart erweitert, daß ich > erst Partition 0 öffne und versuche auf das FAT16 zuzugreifen. Schlägt > dies fehl, dann close ich Partition 0 und versuche es mit Partition -1. > Erst wenn dies fehlschlägt, dann gibt es einen Fehler. Nun, das ist doch genau das Vorgehen, welches ich in meinem Code verwende? > - FAT32-Support angefangen zu implementieren (auch Header-File Option) > > Werde Roland mal einen Patch zukommen lassen - mal sehen, ob er die > Änderungen gebrauchen kann. Schön. Dazu dann alles weitere per Mail. Gruß, Roland
Datum:
> Schön. Dazu dann alles weitere per Mail.
Hhm. Interessiert wäre ich auch, schade das ihr das nicht öffentlich
macht.
Btw: Mein modifizierter SD-Reader funktioniert seit knapp einem Jahr im
Dauereinsatz tadellos.
:-)
Torsten
Datum:
Hallo Torsten, >> Schön. Dazu dann alles weitere per Mail. > > Hhm. Interessiert wäre ich auch, schade das ihr das nicht öffentlich > macht. > Nunja, das wird eh kaum in näherer Zukunft in meinen Code kommen, weil mein kleiner mega168 eh schon mit knappem Speicher kämpft, und von dem braucht FAT32 schon ein gutes Stück mehr. Da müsste ich mir also einen anderen Aufbau z.B. mit mega32 oder gleich einem ARM überlegen. Aber ich denke, Kai ist auch bereit den Patch hier im Forum zu posten... > Btw: Mein modifizierter SD-Reader funktioniert seit knapp einem Jahr im > Dauereinsatz tadellos. > Schön zu hören! Gruß, Roland
Datum:
Sollte den Code nicht größer machen, wenn man FAT32_SUPPORT 0 setzt. Root-Directory klappt schon. Freier Speicher auch fertig. Werde mich nun gleich noch einmal kurz an die Cluster-FAT32-Verkettungsroutinen setzen. War wohl gestern zu blind um den Fehler zu sehen 8) Nevertheless, ja, klar kann (und werde) ich den Patch dann hier auch veröffentlichen.
Datum:
Anbei der angekündigte Patch. Ist leider doch etwas mehr Modifikation geworden ... Auf jeden Fall sollten SDHC-Karten und FAT32 funktionieren. Die SDHC-Initialisierung habe ich derzeit nicht Präprozessorgesteuert gemacht. FAT32 support kann im Header-File deaktiviert werden. Ich hoffe ich habe den Code soweit gut genug aufgeräumt - es waren doch intensivere Debug-Sessions nötig, welche einige debug()-Calls nach sich gezogen haben. Sollte aber alles "DEBUG_FAT16, DEBUG_SD, DEBUG_PARTITION" bzw. "VERBOSE_FAT16, VERBOSE_SD, VERBOSE_PARTITION" geklammert sein und daher bei nicht existenten Defines sauber kompilieren. Im partition.c habe ich außerdem die Partitionserkennung/-prüfung erweitert. Mit den Berechnungen (block >> 9), (block_offset) beim Aufrufen der sd_raw_* void*-Funktionspointer, bin ich noch nicht ganz glücklich. Wenn jemand eine bessere Idee hat ... der Code ist ja nun passend zu den Feiertagen ... Viel Spaß! :) Kai
Datum:
Angehängte Dateien:Hier nun hoffentlich mit Attachment ...
Datum:
Wow, exzellente Arbeit! Ich habe mir das diff-file nur kurz angeschaut. Mehr als 3400 Zeilen, einige neue Dateien. Unmöglich das per Hand in mein Projekt fehlerfrei einzubauen um das mal auszuprobieren. Deswegen meine Frage: Wenn es Dir nichts ausmacht, kannst Du vielleicht den SD-Reader inklusive der neuen Sachen in ein .zip packen und hier veröffentlichen? Der Patch ist ein richtig dicker Brocken... Welche MCU hattest Du zum debuggen, wegen Ram etc.? Torsten
Datum:
Danke für das positive Feedback :) Ich wollte Roland eigentlich erst einmal die Entscheidung zum Einbau überlassen. Kann aber sonst auch gerne mal ein komplettes Zip-File als "FAT32-Version" hochladen. Neue Files sollten eigentlich nicht drin sein. Habe gerade auch noch einmal in den Patch gesehen und konnte keine finden. Welche neuen Files versucht er denn bei dir zu erstellen? Zum debuggen habe ich ein m2561 mit S65-Display verwendet. Den zusätzlichen Speicherverbrauch habe ich auch noch nicht überprüft - hatte hierbei auch auf Roland gehofft, da er ja wohl eine passende Referenz-Plattform zur Verfügung hat und die Werte daher auch einfacher mit seinen vergleichen könnte. (ich hoffe der Code ist nicht zu groß für die von ihm verwendete CPU geworden) Grundsätzlich sollte man natürlich auch die Nachteile von FAT32 bedenken. Der deutlich größere FAT-Table verursacht natürlich einiges an Kosten auf der CPU und auf dem SD-Interface. Die Überprüfung auf freien Speicherplatz (FAT16/FAT32) verdeutlicht dies auch eindrucksvoll. Mit mehr Speicher sähe die Situation anders aus - nicht für den Speicher, aber für die Performance ;) Vielleicht komme ich ja noch dazu einen Patch für 32 oder 64k zu machen. 64k (56k nutzbar) wären für mich sehr elegant, da man dann auch über ein performates .png deflate nachdenken könnte, was für mein Projekt sehr nett wäre. Schaue mir gerade mal die zlib an ...
Datum:
Kai Bankett wrote: > Danke für das positive Feedback :) Gerne. Kein Anfängerwerk btw. > Neue Files sollten eigentlich nicht drin sein. Habe gerade auch noch > einmal in den Patch gesehen und konnte keine finden. Welche neuen Files > versucht er denn bei dir zu erstellen? Oops, Du hast recht. Ich habe mich nur durch "-FAT32" irritieren lassen: --- SD-Card/fat16.c +++ SD-Card-FAT32/fat16.c Wobei der Dateiname nun nicht mehr passt. > Zum debuggen habe ich ein m2561 mit S65-Display verwendet. Den > zusätzlichen Speicherverbrauch habe ich auch noch nicht überprüft - Mit diesem Monster sollte es keine Speicher-Probleme geben. ;) > hatte hierbei auch auf Roland gehofft, da er ja wohl eine passende > Referenz-Plattform zur Verfügung hat und die Werte daher auch einfacher > mit seinen vergleichen könnte. (ich hoffe der Code ist nicht zu groß für > die von ihm verwendete CPU geworden) Er ist mit Sicherheit zu groß. In einen M168 passt das nicht mehr rein. > Grundsätzlich sollte man natürlich auch die Nachteile von FAT32 > bedenken. Der deutlich größere FAT-Table verursacht natürlich einiges an > Kosten auf der CPU und auf dem SD-Interface. Die Überprüfung auf freien > Speicherplatz (FAT16/FAT32) verdeutlicht dies auch eindrucksvoll. > Mit mehr Speicher sähe die Situation anders aus - nicht für den > Speicher, aber für die Performance ;) Das ist ganz klar. Alles hat seinen Preis. Nun mache ich mir Sorgen ob das auch in einen M644 noch rein paßt. Einen M32 mußte ich schnell ersetzen. Der hat zwar noch für den reinen SD-Reader gereicht aber nicht mehr für Erweiterungen. > Vielleicht komme ich ja noch dazu einen Patch für 32 oder 64k zu machen. > 64k (56k nutzbar) wären für mich sehr elegant, da man dann auch über > ein performates .png deflate nachdenken könnte, was für mein Projekt > sehr nett wäre. Schaue mir gerade mal die zlib an ... Ähm, was meinst Du mit 32 oder 64k, SRAM oder Cluster-Größe etwa? Ein paar typos habe ich auf die Schnelle gefunden:
+debug(S_PSTR("CHAOSMAN D0")); +#ifdef DEBuG_FAT16 |
Datum:
Torsten S. wrote: > Oops, Du hast recht. Ich habe mich nur durch "-FAT32" irritieren lassen: > --- SD-Card/fat16.c > +++ SD-Card-FAT32/fat16.c > Wobei der Dateiname nun nicht mehr passt. Du mußt patch mit der Option -pX aufrufen, je nachdem in welchem Verzeichnis du dich befindest. Sollte funktionieren, wenn du den Patch in das Verzeichnis legst, in dem sich auch die zu patchenden Files befinden und -p0 verwendest. Auf jeden Fall ist es beim GNU-patch unter Unix so. Ich weiß ja nicht, ob du diesen benutzt hast, sonst mußt du schauen, wie die Option zum abschneiden des 1. Directories bei der von dir verwendeten Applikation benutzt wird. > > Er ist mit Sicherheit zu groß. In einen M168 passt das nicht mehr rein. > Hm. Das ist schade. Man könnte natürlich noch Ballast rauswerfen. SDHC z.B., wobei FAT32 dann natürlich nicht mehr wirklich Sinn macht. > Das ist ganz klar. Alles hat seinen Preis. > Nun mache ich mir Sorgen ob das auch in einen M644 noch rein paßt. Einen > M32 mußte ich schnell ersetzen. Der hat zwar noch für den reinen > SD-Reader gereicht aber nicht mehr für Erweiterungen. Wie gesagt, eindampfen kann man sicherlich noch. Ich müßte nur wissen, wieviel fehlt. So viel ist nun auch wieder nicht dazu gekommen. Man könnte sich natürlich nur auf FAT32 beschränken. Dann spart man sich einen Teil dessen, was dazu gekommen ist. > Ähm, was meinst Du mit 32 oder 64k, SRAM oder Cluster-Größe etwa? War auf die Menge an RAM bezogen. Mit mehr Speicher kann man mehr cachen. Den FAT komplett, oder auch nur teilweise, zu cachen würde eine Menge bringen. > Ein paar typos habe ich auf die Schnelle gefunden: >
+debug(S_PSTR("CHAOSMAN D0")); > +#ifdef DEBuG_FAT16 |
Ja, danke! Ist korriegiert. Kai
Datum:
Hallo zusammen, ich versuche mich gerade daran, mit einem ATmega324P eine SD-Karte anzusteuern; dabei verwende ich allerdings das USART im SPI-Modus anstelle des regulären SPI, da ich dieses in meiner Schaltung anderweitig benutze. Schreiben und Lesen funktioniert im Prinzip: in einem ersten Versuch habe ich mit sd_raw_write()/sd_raw_sync() 250 Byte auf die Karte geschrieben und konnte die mit sd_raw_read() auch wieder lesen. In meinem derzeitigen Programm rufe ich zunächst die Funktionen auf: sd_raw_init(); partition_open(...); fat16_open(...); fat16_get_dir_entry_of_path(...); fat16_open_dir(...); dabei treten keine Fehler auf. Dann versuche ich, eine Datei zu erzeugen und etwas hineinzuschreiben: fat16_create_file(dd,"datei.tst",&dir_entry); fd = fat16_open_file(fs,&dir_entry); // fat16_resize_file(fd,1500); fat16_write_file(fd,"Hallole!",8); fat16_close_file(fd); sd_raw_sync(); Die Datei wird zwar angelegt, sie wird beim Schreiben aber nicht vergrößert. Kontrolle am PC zeigt eine Datei der Länge 0. Wenn ich die nun am PC beschreibe, kann auch der Controller den String hineinschreiben. Der Aufruf von fat16_resize_file() hilft nicht weiter, da bleibt das Programm hängen beim Aufruf von device_write() in fat16_write_dir_entry() (Zeile 1764 in fat16.c) Hat da jemand eine Idee, was da schiefläuft? Danke im voraus Martin
Datum:
Hallo Martin, Könntest Du bitte genauer sagen, wo sd_raw_write() hängen bleibt? Des weiteren könntest Du versuchen herauszufinden, warum es nicht hängen bleibt, wenn fat16_write_dir_entry() aus fat16_create_file() oder fat16_write_file() heraus aufgerufen wird. Schalte doch mal für Deine Tests SD_RAW_WRITE_BUFFERING aus, dann treten mögliche Schreibprobleme sofort auf und nicht erst dann, wenn der Puffer geschrieben wird. Ehrlich gesagt vermute ich eher ein Hardwareproblem. Aber mal sehen... Gruß, Roland
Datum:
Hallo Roland, das Problem tritt bereits bei fat16_create_file(), nur nicht so offensichtlich. Ich habe gestern abend noch folgendes ausprobiert: uint8_t result = 0; if ( !fat16_create_file(dd,"datei.1",&dir_entry) ) result++; if ( !fat16_create_file(dd,"datei.2",&dir_entry) ) result++; if ( !fat16_create_file(dd,"datei.3",&dir_entry) ) result++; if ( !fat16_create_file(dd,"datei.4",&dir_entry) ) result++; if ( !fat16_create_file(dd,"datei.5",&dir_entry) ) result++; if ( !fat16_create_file(dd,"datei.6",&dir_entry) ) result++; if ( !fat16_create_file(dd,"datei.7",&dir_entry) ) result++; if ( !fat16_create_file(dd,"datei.8",&dir_entry) ) result++; if ( !fat16_create_file(dd,"datei.9",&dir_entry) ) result++; sd_raw_sync(); if ( !result ) for (;;) PORTB ^= 0x0E; // alles ok else for (;;); // Fehler! Wenn ich SD_RAW_WRITE_BUFFERING eingeschaltet habe, wird nur datei.1 angelegt. Schalte ich dagegen SD_RAW_WRITE_BUFFERING aus, werden datei.1 bis datei.4 oder datei.5 erzeugt, außerdem datei.9. Aber nur unter Linux sind die Dateien auch zu sehen, manchmal wird eine Datei auch doppelt angezeigt! Windows zeigt nur ein leeres Verzeichnis an. Da ich in Deinem Code die Funktionen sd_raw_init(), sd_raw_send_byte() und sd_raw_send_byte() geändert habe, könnte natürlich auch hier irgend etwas passieren, obwohl ich das weniger glaube, da ich das doppelt und dreifach gegen das Datenblatt verglichen habe. Ich habe mir gestern noch ein STK500 und eine Handvoll Controller bestellt, die sind vorhin angekommen. Mal sehen, ob ich Deinen Originalcode da zum Laufen bringe und da zu irgendeiner Erkenntnis komme. Gruß Martin
Datum:
Hallo Martin, Mir fehlen einige Infos, um selbst irgendwas testen zu können. 1. Was ist denn der Wert von result in Deinem Test? 2. Kannst Du mir ein Karten-Image zukommen lassen? 3. Werden die Dateien im Wurzelverzeichnis oder in einem Unterverzeichnis angelegt? 4. Wie hast Du denn die Karte formatiert? Du solltest die Karte nach jedem Test löschen, so dass evtl. kaputte FAT-Strukturen nicht weitere Effekte auslösen können. 5. Wie stark ausgelastet ist der Controller sonst? Besteht die Möglichkeit von Stack-Überläufen? Gruß, Roland
Datum:
Angehängte Dateien:Hallo Roland, > 1. Was ist denn der Wert von result in Deinem Test? Bei ausgeschaltetem SD_RAW_WRITE_BUFFERING hat result den Wert 0, obwohl nicht alle Dateien angelegt werden. Im Fall von Doppeleinträgen, d.h. wenn derselbe Dateiname zweimal angezeigt wird, erhalte ich den Wert 4. Schalte ich SD_RAW_WRITE_BUFFERING ein, erhalte ich ebenfalls den Wert 0, wenn ich fat16_create_file() einmal aufrufe. Rufe ich die Funktion zweimal oder öfter auf, bleibt das Programm hängen und ich komme erst gar nicht zu meiner Endlosschleife, die erste Datei (datei.1) wird aber angelegt. Für die Tests habe ich die Karte jedesmal formatiert. > 2. Kannst Du mir ein Karten-Image zukommen lassen? Ich habe 1MB-Images von drei verschiedenen Karten angehängt, jeweils mit (*-mb) und ohne (*-ob) Buffering. > 3. Werden die Dateien im Wurzelverzeichnis oder in einem > Unterverzeichnis angelegt? Die Dateien stehen im Wurzelverzeichnis. > 4. Wie hast Du denn die Karte formatiert? Mit mkdosfs -F16 /dev/sda1 unter Linux. > 5. Wie stark ausgelastet ist der Controller sonst? Im Moment dreht er nur Däumchen, d.h. ich setze lediglich ein paar Port-Pins und versuche dann, die Karte anzusprechen, sonst passiert noch nichts. Gruß Martin
Datum:
Hallo, ein ATmega8 bedient eine SD-Karte (FAT16), ist allerdings nur Assembler: Beitrag "SD-Karte Initialisierung Read Write FAT ATmega8 (Assembler)" Gruß Bernhard
Datum:
Servus Martin, Nach kurzem Überfliegen der Images kann ich schonmal soviel sagen: 1. Das was Windows und Linux anzeigen, ist plausibel und durch geringfügig andere FAT-Implementationen erklärbar. 2. Ohne Pufferung fehlen die LFN-Verzeichniseinträge bzw. sind leer. Mit Pufferung sind sie vorhanden. 3. Der Platz für die Verzeichniseinträge der fehlenden Dateien ist zwar vorhanden, enthält aber auch nur Nullen. 4. Die doppelt vorhandenen Dateien sind so tatsächlich auch im Verzeichnis eingetragen. Da stimmt irgendetwas überhaupt nicht. Entweder die SD-Routinen geben Erfolg zurück, obwohl nichts geschrieben wurde, oder es gibt einen Bug an anderer Stelle. Wie machst Du denn die Stromversorgung und das Level-Shifting für die Speicherkarte? Magst Du mir vielleicht Dein Testprogramm inklusive der von Dir durchgeführten Änderungen an sd_raw.c schicken? Evtl. fällt mir da noch irgendwas auf. Vielleicht finde ich morgen etwas Zeit, um Deinen Test nachzubauen und evtl. den Fehler zu reproduzieren. Viele Grüße, Roland
Datum:
Angehängte Dateien:Hallo Roland, meine Schaltung läuft mit 3,3V; damit sollte die Karte eigentlich zufrieden sein. Der externe Takt ist 18MHz, den internen Systemtakt habe ich sicherheitshalber auf die Hälfte reduziert. Mein Testprogramm habe ich angehängt, die Hauptänderungen sind in sd_raw_init(), sd_raw_send_byte() und sd_raw_rec_byte() (s. aenderungen). Gruß Martin
Datum:
Angehängte Dateien:Hallo Martin, Gestern konnte ich Deine Probleme teilweise reproduzieren. Bei mir scheiterte allerdings nur das korrekte Anlegen der achten Datei. Nach viel erfolglosem Debugging hat sich rausgestellt, dass (zumindest bei mir) tatsächlich der Stack in den statisch allokierten Heap reingewachsen ist. Sobald ich nicht so viel Speicher verbraucht habe, indem ich z.B. die Dateien nur noch einstellig benannt habe, lief alles so wie es sollte. Ich habe mir mal Dein Programm bzgl. des benutzten Speichers angeschaut: - Puffer 512+5 Bytes - Handles für Partition, Dateisystem, Dateien, Verzeichnisse 17+26+51+94 Bytes - Stack in main(): ca. 95 Bytes (zumindest mein Compiler optimiert die insgesamt 252 Bytes großen aber unbenutzten Variablen weg) - Zeichenfolgen in main(): 72 Bytes - Stack für FAT-Aufrufe: schätzungsweise ca. 60 Bytes Insgesamt sind das knapp 940 Bytes. Dein Controller hat 2 kBytes, es sollte also nicht zu Problemen kommen. Dennoch könntest Du mal versuchen, mit den folgenden Änderungen Speicher zu sparen: - Dateien nur mit einem Buchstaben benennen. - Für das Öffnen des Wurzelverzeichnisses und das Anlegen der Dateien den selben dir_entry verwenden (fat16_open_dir() macht intern eine Kopie, die im Handle abgelegt wird). - Die unbenutzten Variablen buffer und fd zur Sicherheit entfernen. Mein Testprogramm findest Du angehängt. Zur Laufzeit gibt es hier folgendes aus:
manuf: 0x06 oem: RK prod: SD rev: 00 serial: 0x000004b1 date: 12/5 size: 127139840 copy: 0 wr.pr.: 0/0 format: 0 free: 126644224/126693376 1: success1 2: success2 3: success3 4: success4 5: success5 6: success6 7: success7 8: success8 9: success9 |
Linux zeigt dann an:
drwxr-xr-x 2 root root 16K 1970-01-01 01:00 ./ drwxr-xr-x 24 root root 4,0K 2007-10-15 09:04 ../ -rwxr-xr-x 1 root root 0 1980-01-01 01:00 1* -rwxr-xr-x 1 root root 0 1980-01-01 01:00 2* -rwxr-xr-x 1 root root 0 1980-01-01 01:00 3* -rwxr-xr-x 1 root root 0 1980-01-01 01:00 4* -rwxr-xr-x 1 root root 0 1980-01-01 01:00 5* -rwxr-xr-x 1 root root 0 1980-01-01 01:00 6* -rwxr-xr-x 1 root root 0 1980-01-01 01:00 7* -rwxr-xr-x 1 root root 0 1980-01-01 01:00 8* -rwxr-xr-x 1 root root 0 1980-01-01 01:00 9* |
Falls Du Dich mit der Struktur der Verzeichniseinträge einigermaßen auskennst, die sehen dann korrekt z.B. so aus:
00048c00 41 31 00 00 00 ff ff ff ff ff ff 0f 00 6c ff ff |A1...........l..| 00048c10 ff ff ff ff ff ff ff ff ff ff 00 00 ff ff ff ff |................| 00048c20 31 20 20 20 20 20 20 20 20 20 20 00 00 00 00 00 |1 .....| 00048c30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00048c40 41 32 00 00 00 ff ff ff ff ff ff 0f 00 2c ff ff |A2...........,..| 00048c50 ff ff ff ff ff ff ff ff ff ff 00 00 ff ff ff ff |................| 00048c60 32 20 20 20 20 20 20 20 20 20 20 00 00 00 00 00 |2 .....| 00048c70 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00048c80 41 33 00 00 00 ff ff ff ff ff ff 0f 00 ec ff ff |A3..............| 00048c90 ff ff ff ff ff ff ff ff ff ff 00 00 ff ff ff ff |................| 00048ca0 33 20 20 20 20 20 20 20 20 20 20 00 00 00 00 00 |3 .....| 00048cb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| ... |
Beim Debuggen ist mir zwar noch etwas anderes aufgefallen, dies betrifft jedoch nur das Auslesen von (sehr großen) Verzeichnissen und hat nichts mit Deinen Problemen zu tun. Wahrscheinlich gebe ich dazu dann später eine neue Release raus. Viele Grüße, Roland
Datum:
Guten Tag zusammen Ich möchte für ein späteres Projekt (GPS-Logger) ein SD Karte Testmässig ansteuern. Nun habe ich mit einem Atmega48 die Testschaltung aufgebaut. Die Speisung der SD Karte erfolgt über einen 3.3V Spannungsregler. Die Pegelanpassung der Datenleitungen erfolgt über Spannungsteiler. Die SD Karte ist eine Panasonic 256MB. Der Grund warum ich hier schreibe ist, dass ich bis jetzt das Initialisieren der Karte noch nicht hinbekommen habe. Ich hoffe ihr könnt mir irgendwelche Tipps geben welche ich noch zu beachten habe. Falls ihr noch Infos bezüglich der Hardware oder sonstigem braucht werde ich das natürlich nachliefen. Mir fällt momentan nichts relevantes mehr ein. Die Software habe ich soweit anpassen müssen das sie in den Atmega48 passt, das heisst es ist nur noch fast das Init mit fast allen benötigten Funktionen vorhanden. sd_raw_read() konnte ich aufgrund des Platzmangels nicht mehr implementieren. Aufgrund des Platzproblems stelle ich noch eine weiter Frage. Ist es normal das die Programme so gross sind? Programmgrösse ohne FAT Unterstützung : ca 9kb Programmgrösse mit FAT Unterstützung: ca 40kb Ich danke euch schon jetzt für eure Mühe. Gruss
Datum:
Hallo Roland, hast Du bei Deinem Test das Original-SPI oder das USART im SPI-Modus benützt? Ich habe vorhin meinen Kartensockel auf das Original-SPI umgelötet, und damit funktionert alles; ich kann die Dateien anlegen, eine öffnen und etwas einschreiben, die Datei wird dabei automatisch vergößert. Das Ergebnis sieht folgendermaßen aus:
0000b000 41 64 00 61 00 74 00 65 00 69 00 0f 00 ae 2e 00 |Ad.a.t.e.i......| 0000b010 31 00 00 00 ff ff ff ff ff ff 00 00 ff ff ff ff |1...............| 0000b020 64 61 74 65 69 20 20 20 31 20 20 00 00 00 00 00 |datei 1 .....| 0000b030 00 00 00 00 00 00 00 00 00 00 02 00 08 00 00 00 |................| 0000b040 41 64 00 61 00 74 00 65 00 69 00 0f 00 6f 2e 00 |Ad.a.t.e.i...o..| 0000b050 32 00 00 00 ff ff ff ff ff ff 00 00 ff ff ff ff |2...............| 0000b060 64 61 74 65 69 20 20 20 32 20 20 00 00 00 00 00 |datei 2 .....| 0000b070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| (...) 0000b1c0 41 64 00 61 00 74 00 65 00 69 00 0f 00 b0 2e 00 |Ad.a.t.e.i......| 0000b1d0 38 00 00 00 ff ff ff ff ff ff 00 00 ff ff ff ff |8...............| 0000b1e0 64 61 74 65 69 20 20 20 38 20 20 00 00 00 00 00 |datei 8 .....| 0000b1f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 0000b200 41 64 00 61 00 74 00 65 00 69 00 0f 00 f0 2e 00 |Ad.a.t.e.i......| 0000b210 39 00 00 00 ff ff ff ff ff ff 00 00 ff ff ff ff |9...............| 0000b220 64 61 74 65 69 20 20 20 39 20 20 00 00 00 00 00 |datei 9 .....| 0000b230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 0000f000 48 61 6c 6c 6f 6c 65 21 00 00 00 00 00 00 00 00 |Hallole!........| 0000f010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| |
Da scheint bei meinen Versionen von sd_raw_send_byte() und sd_raw_rec_byte() der Wurm drin zu sein! Gruß Martin
Datum:
Hallo Martin, Schön zu hören, dass Du es zumindest mit dem normalen SPI am Laufen hast. Meine Tests waren wie immer auch mit der normalen Schnittstelle, meine Platine sieht gar nichts anderes vor. Habe mir in Deinem Code auch die Initialisierung sowie das Senden und Empfangen über den USART-SPI angeschaut, es ist mir aber nichts aufgefallen. Vielleicht hat es etwas mit der zusätzlichen Pufferung im Vergleich zum normalen SPI zu tun (s. Datenblatt Kap. 19.7)? Oder es gibt ein Timing-Problem mit dem Chip-Select? Naja, das ist eher unwahrscheinlich. Viele Grüße, Roland
Datum:
@stucmath Was machst Du mit einer SD-Kartenunterstützung, in der Du sd_raw_read() weglässt?!? Deine Codegrößen sind nicht normal, Du solltest einmal die Einstellungen Deines Compilers überprüfen und dort eine Größenoptimierung einstellen. Aber selbst mit der Größenoptimierung wirst Du auf dem ATmega48 nicht glücklich. Meine Beispielanwendung braucht für Nur-Lese-Unterstützung mindestens einen mega8/88, mit Schreibunterstützung einen mega16/168. Gruß, Roland
Datum:
Na ja das bringt eigentlich wirklich nichts. Aber ich wollte nur für denn anfang erreichen das ich die SD Karte Initialisieren kann. Das sollte doch auch ohne sd_raw_read() klappen? Ich kompiliere meine Projekte immer über eine build.bat Datei. Die Optimierung habe ich auf -Os gestellt. Sollte doch eigentlich in Ordnung sein. Mit Lese- Schreibunterstützung meinst du mit oder ohne FAT? Ich werde mir also am besten einmal ein Testboard mit einem Atgema32 aufbauen. Danke für deine Hilfe Gruss
Datum:
Ja klar, für die Initialisierung selbst brauchst Du nur sd_raw_init(). Die Optimierung ist so auch in Ordnung. Wo liest Du denn Deine Codegrößen ab? Doch nicht an der Größe der Ausgabe des Linkers? Benutze (am Beispiel des sd-readers) avr-size -A sd-reader.out In der Ausgabe entspricht der Flash dem Segment .text und das statisch allokierte RAM wird in die Segmente .data und .bss ausgegeben. Die Angabe der Controllergrößen bezog sich auf meine Anwendung, also mit FAT-Unterstützung und der Mini-Shell über UART. Gruß, Roland
Datum:
Hallo Roland, RTFM kann ich da nur sagen! Deine Vermutung, es könnte mit der zusätzlichen Pufferung beim USART-SPI zu tun haben, war goldrichtig. Meine Sendefunktion sah so aus:
void sd_raw_send_byte(uint8_t b)
{
while ( !(UCSR0A & (1<<UDRE0)) );
UDR0 = b;
}
|
Dies scheint zunächst richtig zu sein, hat aber tatsächlich einen gravierenden Fehler. Da mit dem Sendebyte auch ein Byte empfangen wird, bleibt bzw. wird das UDRE0-Bit gelöscht, und beim nächsten Funktionsaufruf bleibt das Programm in der while-Schleife hängen. Um dieses Bit zu setzen, muß ich das Empfangsbyte lesen. Das habe ich nun ergänzt:
void sd_raw_send_byte(uint8_t b)
{
while ( !(UCSR0A & (1<<UDRE0)) );
UDR0 = b;
while ( !(UCSR0A & (1<<RXC0)) );
b = UDR0;
}
|
Mit diesen zwei zusätzlichen Zeilen läuft jetzt alles einwandfrei! Herzlichen Dank für Deine Unterstützung und viele Grüße! Martin
Datum:
Hmm da habe ich doch wieder einmal etwas gelernt. Habe die .hex grösse direkt am file gelesen. Mit avr-size -A sd_reader.hex zeigt es mir 14470 byte an also 14.1kbyte. Ich denke so ist alles in Ordnung. Danke für den Tipp. Habe nun auf einen Atmega32 umgestellt. Leider funktioniert das Init dort auch nicht. Die Serielle Schnittstelle meldet nur: MMC/SD initialization failed Ich gehe mal schwer davon aus das dies ein Hardware Fehler sein wird. Aber was könnte das sein? Wie schon gesagt für die Speisung verwende ich einen Spannungsregler (3.3V). Als Pegelwandler sind Widerstände zuständig. Diese könnten durch die Toleranzen so zwischen 3.0 - 3.2V liegen. Nun da ich keine noch keine Erfahrung mit SD-Karten habe frage ich hier wo könnten denn Fehler aufgetaucht sein? Ich hoffe du (ihr) könnt mir weiterhin hilfreiche Tipps geben. Gruss
Datum:
Hallo, mir geht es da ähnlich. Anbindung der MMC ist nach dem einfachen Schema von Ullrich Radig erfolgt. Am Oszi sehe ich das sich auf CS, DI und CLK etwas tut. Auf DO ist aber schweigen. VCC der Karte liegt bei 3.29V. Das gleiche Verhalten habe ich mit zwei Karten (1GB Kingston, 2GB no-name). Softwareseitig geht dann natürlich das reset Kommando schief, da dies einen definierten Rückgabewert von der Karte erwartet. Tipps wären hochwillkommen. Gruß Malte
Datum:
@Malte, stucmath Hmm, mehr als auf meinen Schaltplan zu verweisen kann ich leider nicht. Der funktioniert bei mir ohne Probleme. Die Dioden-Lösung ist allerdings nicht optimal. Bei Zugriffen auf die Karte sackt die Versorgungsspannung durch den Stromfluss von ca. 3,7 Volt auf Werte um die 3,3 Volt ab. Mag sein, dass das die ein oder andere Karte stört, meine laufen glücklicherweise problemlos. Gruß, Roland
Datum:
Hallo Roland, danke für die schnelle Antwort. Bei mir kommt statt der Dioden ein LM317 zum Einsatz der die 3,3V bereitstellt. Komisch... Gruß Malte
Datum:
Hallo Roland und Malte Bei mir funktioniert es mittlerweile. Der Fehler war das ich aus mir unbekannten Gründen (Dummheit) die MISO Leitung auch über einen Spannungsteiler geschalten habe. @Roland Ich danke dir vielmals für deine Hilfe und auch für die Software. Die ist einfach nur Klasse. @Malte Roland hatte hier einmal geschrieben das wenn man mit einem Spannungsregler arbeitet muss darauf geachtet werden, dass die ein wenig unter den 3.3V liegen. Deshalb habe ich meinen Spannungsteiler folgendermassen gewählt: 3.3K 2K Ergibt dann etwa eine Spannung von 3.1V Gruss
Datum:
Also, ich habe das eben durchgemessen. DI, CS, CLK liegen alle bei 3,2V. Versorgungspannung bei 3,29V) Bin reichlich ratlos... Malte
Datum:
Malte Das tut ja richtig weh Dich leiden zu sehen. ;) Nur so ein paar Tips: Der LM317 ist ca. 20 Jahre alt und eher ungeeignet um 3.3V für eine SD-Karte bereit zu stellen weil er ständig eine Mindestlast von einigen mA zum funktionieren benötigt. Wenn Du das sicher stellen kannst ist das o.k. - sonst aber kein Beitrag zum Thema Energie sparen. Es gibt modernere IC's dafür. Du kannst an jeder beliebigen Stelle in Roland's SD-Reader ein paar zusätzliche printf's einbauen um zu beobachten an welcher Stelle es genau hakt. Diese kannst Du Dir ganz in Ruhe via Hyperterminal etc. am PC angucken. Besonders spannend sind die Sachen die in "sd_raw.c" in "sd_raw_init()" passieren. Guck Dir genau an ob Du auch einen Karten-Slot hast der Kontakte für configure_pin_available() (=SD-Card eingesteckt) und configure_pin_locked() (=SD-Card schreibgeschützt) bereitstellt. Wenn das nicht der Fall ist muß der Original-Code angepaßt werden! Viel Glück, Torsten
Datum:
Hallo, nach ich mit einer "billigen" SD-Karte von Reichelt Probleme hatte, hab ich's jetzt mit einer etwas teureren Karte vom Conrad fast hinbekommen. Ich habe die letzte Version von Roland auf einem ATMega168 laufen, einzige Änderung zum Orginal Source Code ist, dass ich die Abfragen locked und available folgendermassen geändert habe: in sd_raw_config.h
#define get_pin_available() 1 // Change ((PINC >> PC4) & 0x01) #define get_pin_locked() 1 // Change ((PINC >> PC5) & 0x01) |
und in sd_raw.c
uint8_t sd_raw_available()
{
return 1; // change get_pin_available() == 0x00;
}
uint8_t sd_raw_locked()
{
return 0; // change get_pin_locked() == 0x00;
}
|
Jetzt zu meinem Problem: alle Shell Befehle funktionieren, bis auf cat <file> und write <file> <offset>, beim Aufruf dieser Funktionen hängt das Programm sich auf oder kommt mit der Initialisierung wie nach einem Reset zurück. Kennt jemand das Problem ? Gruss Reinhard
Datum:
Hallo Reinhard, in Deiner sd_raw_config.h sollte folgendes stehen (s.a. weiter oben):
#define configure_pin_available() #define configure_pin_locked() #define get_pin_available() 0 #define get_pin_locked() 0 |
Damit kannst Du die originalen sd_raw_locked() und sd_raw_available() unverändert lassen. Mit Deinem:
#define get_pin_locked() 1 |
wird sd_raw_write() nie ausgeführt (s. sd_raw.c). Gruß Martin
Datum:
Servus Reinhard, Wie Martin schon korrekt ausgeführt hat, musst Du das #define auf 1 ändern, sonst nimmt meine Software an, dass der Schreibschutz aktiviert ist. Das liegt daran, dass in meiner Schaltung die Port-Pins gegen Masse geschaltet werden, wenn der Schutz aktiv ist. (Der Schreibschutz bei den MMC/SD-Karten ist allein durch die Software realisiert. Der Schalter an der Karte ist nur ein Kunststoffnippel, von dem der Kartencontroller nichts weiß. Erst die Host-Software kann über einen Schalter im Sockel die Position des Schreibschutzschalters feststellen und verweigert gegebenenfalls den Schreibzugriff.) Viele Grüße, Roland
Datum:
Hallo Martin, hallo Roland ich habe eure vorgeschlagene Änderung durchgeführt. Das führt jetzt zu einer "sauberen" Programmierung, wenn die Schalter für Locked und Available fehlen, beseitigt aber nicht das beschriebene Problem mit "cat" und "write". Schreiben konnte ich ja auch schon vorher, "touch", "rm" und "mkdir" als Shell Befehle funktionieren ja. Hier mal ein Abdruck des Terminals:
> manuf: 0x1b oem: SM prod: SMI rev: 10 serial: 0x099da84f date: 7/7 size: 1017643008 copy: 0 wr.pr.: 0/0 format: 0 free: 1016758272/1017249792 > ls abc/ 0 file.txt 16 a/ 0 > > cat file.txt |
ab hier hängt's. Ein weiteres Beispiel, wenn der File in einem Unterverzeichnis ist:
manuf: 0x1b oem: SM prod: SMI rev: 10 serial: 0x099da84f date: 7/7 size: 1017643008 copy: 0 wr.pr.: 0/0 format: 0 free: 1016758272/1017249792 > cd abc > > ls ./ 0 ../ 0 abc.txt 24 > > cat abc.txt manuf: 0x1b oem: SM prod: SMI rev: 10 serial: 0x099da84f date: 7/7 size: 1017643008 copy: 0 wr.pr.: 0/0 format: 0 free: 1016758272/1017249792 > |
Hier springt das Programm an den Anfang. Ich hoffe, dass der Fehler jetzt klarer beschrieben ist und ihr helfen könnt. Gruss Reinhard
Datum:
Hallo Reinhard, Nachdem Du (bis auf die zwei besprochenen Änderungen) genau den gleichen Code benutzt wie ich und auch den gleichen Controller, tippe ich jetzt einfach mal auf die Hardware. Könntest Du diesen bitte schildern oder einen Schaltplan posten? Interessant ist insbesondere die Anbindung der Karte an den Controller und die Stromversorgung. Falls das alles unverdächtig ist, könntest Du vielleicht auch bitte ein Karten-Image erstellen und mir zuschicken. Eventuell finde ich am Donnerstag Zeit, um mal wieder eine Debugging-Sitzung einzulegen... Gruß, Roland
Datum:
Hallo Roland, erst mal Danke für deine super-schnelle Reaktion. Zu meiner HW: ich benutze das Development Board von myavr.de, allerdings abweichend von der Ursprungsversion mit einem ATMega168. Schaltplan dazu unter http://myavr.de/download/techb_myavr_board_lpt.pdf. Getaktet wird das Board mit 3,6864 MHz. Eine Besonderheit ist vielleicht, dass das Board aufgrund des 6V Spannungsreglers und der Reihendiode mit ca. 5,3V betrieben wird. Die SD-Karte ist wie in deinem Schaltplan mit Spannungsteiler (3,3k gegen Masse, 1,8k in Reihe) an die Datenports angebunden. DATA OUT direkt an MISO. Die SD-Karte wird mit einem LM317 mit 3,3V versorgt. Da der Spannungsteiler die Datenports geringfügig über 3,3V zieht, habe ich auch mit einer Versorgungsspannung von 3,5V probiert, was aber keine Veränderung zeigte. Die SD-Karte ist eine 1GB von Transcend, gleiches Verhalten aber auch bei einer 2GB Karte. Ich denke eher, dass der Fehler in der SW zu suchen ist. Ich habe zumindest den Fehler durch Debug-Ausgaben auf dem Terminal soweit eingrenzen können, dass sich dass Programm bei Eingabe von "cat <file>" in folgender IF Abfrage aufhängt (Funktion: uint8_t fat16_read_root_dir_entry(const struct fat16_fs_struct* fs, uint16_t entry_num, struct fat16_dir_entry_struct* dir_entry)) - ca. Zeile 398 in fat16.c
if(!device_read_interval(header->root_dir_offset, buffer, sizeof(buffer), header->cluster_zero_offset - header->root_dir_offset, fat16_dir_entry_seek_callback, &arg) || arg.entry_offset == 0 ) |
Leider hören da meine C-Kenntnisse bei der Fehlersuche auf. Aber vielleicht hilft dir das ja, den Fehler einzugrenzen. Wenn du glaubst mit einem Karten-Image weiterzukommen, schick ich dir das gerne zu, kommt dann separat per Mail. Ich danke dir nochmals für deine freundliche Hilfe Gruss Reinhard
Datum:
Hallo Reinhard, Die Variable device_read_interval ist ein Funktionspointer auf sd_raw_read_interval(), welche wiederum sd_raw_read() mehrfach aufruft. Wenn er also in der von Dir zitierten if-Abfrage hängen bleibt, müsstest Du in den genannten Funktionen in sd_raw.c weiterforschen. An dieser Stelle können durchaus Hardware-Probleme eine Rolle spielen, etwa wenn die Karte nicht korrekt antwortet. Wenn ich Dein Karten-Image habe, werde ich dieses auf meine Karte schreiben und sehen, ob vielleicht bestimmte Parameter des Dateisystems meinem Code Schwierigkeiten machen. Gruß, Roland
Datum:
Hallo Roland & Rest, ich habe vor eine Micro SD Karte auf meiner neuen Propellerclock (50 RGB LEDs) mitdrehen zu lassen. Erst dachte ich an externes flash rom, auf das die Bilder beim Bootvorgang zwischengespeichert werden, jetzt ist es mir aber gelungen die CPU Last auf unter 30% für die Ansteuerung der LED Treiber zu reduzieren und ich denke drüber nach den Flash Rom komplett wegzulassen. Die Sache ist nur, dass ich jede Sekunde 687kByte brauche und das Holen dieser Daten am Besten innerhalb von 50% CPU Last bewältigen möchte. Unterm Strich komme ich auf eine benötigte Lesegeschwindigkeit von knapp 1,4 MByte/s Meine Frage an euch wäre jetzt ob das mit dem Code überhaupt möglich ist. SPI Frequenz wäre 8MHz, als Controller hatte ich wegen der benötigten I/Os eigentlich den mega128 eingeplant, vielleicht ginge jetzt ja auch ein mega32? Gruß Kai
Datum:
habe gerade nochmal den Taschenrechner bemüht und dabei ist mir aufgefallen, dass eine 8MHz Taktfrequenz dafür gar nicht ausreichen würde... Habe also ein wenig umstrukturiert, brauche jetzt auch etwas über 30% CPU, komme aber "nur" noch auf 430kByte in einer Sekunde, bei 50% CPU wären das dann 860kByte/s oder 6880kBit/s, was mit 8MHz SPI schaffbar wäre. Wo es der AVR jetzt schafft, geht das dann auch mit dem Programm oder wird zuviel Rechenzeit für den Empfang/Pufferung verbraten?
Datum:
Hallo Kai, Aufgrund meiner Erfahrungen denke ich nicht, dass Du das hinbekommen wirst. Zumindest nicht mit FAT und ohne viel(!) Pufferspeicher, den Du Dir ja eigentlich sparen wolltest. Wenn Du die Karte ohne Dateisystem benutzt, und ein Interrupt-basiertes Lesen der SD-Karte implementierst, könnte es vielleicht gehen. Doch selbst dann ist Dein Vorhaben sehr knapp am Limit der maximalen ISP-Frequenz. Die Ansteuerung der Karte benötigt viele Wartezyklen und die Übertragung vieler Dummy-Bytes, die die Netto-Datenrate weit unter das theoretische SPI-Limit drücken. Von dem Overhead eines Dateisystems ganz zu schweigen... Du müsstest also Deine Anforderungen an die Datenrate noch erheblich drücken... Viele Grüße, Roland
Datum:
Hi Roland, das ist aber doof :( weiter drücken geht leider nicht ohne die Bildwiederholfrequenz (momentan 20/s) zu senken. Was ich mir vorstellen könnte wäre die Frequenz auf 10 Bilder/s zu drücken und damit einen Faktor 2 rauszuholen. Dann würde ich ein Bild eben zweimal anzeigen... allerdings brauche ich dann auch einen Puffer, in den ein ganzes Bild reinpasst, welches aber 43kByte groß ist... Da ich sowieso schon länger vorhabe eine SD Karte anzusteuern und die Sockel auch schon länger habe, bin ich gerade dabei eine Schaltung auf Lochraster aufzubauen (ja, mein Sockel passt auf Lochraster). Als µC benutze ich einen mega8. Da ich aber ein fauler Codevision User bin, werde ich deinen Code wohl in Codevision übersetzen müssen :( Werde hoffentlich nicht der einzige sein, der davon profitiert^^ Gruß Kai
Datum:
@ Reinhard Habe jetzt mal Dein Image auf meine Karte gespielt:
manuf: 0x06 oem: RK prod: SD rev: 00 serial: 0x000004b1 date: 12/5 size: 127139840 copy: 0 wr.pr.: 0/0 format: 0 free: 1016758272/1017249792 > ls abc/ 0 file.txt 16 a/ 0 > cat file.txt 00000000: 61 62 63 64 65 66 67 0a 00000008: 31 32 33 34 35 36 37 0a > cd abc > ls ./ 0 ../ 0 abc.txt 24 > cat abc.txt 00000000: 31 32 33 34 35 36 37 38 00000008: 39 30 0a 61 62 63 64 65 00000010: 66 67 68 69 6a 0a 20 0a |
Es funktioniert also prinzipiell. Ich hatte aber hin und wieder Probleme mit dem Wechsel in das Verzeichnis. Nach ein bisschen Debugging denke ich, dass dieses Problem, genauso wie Deines, an der Speicherknappheit liegt. Ich würde Dir empfehlen, meine Mini-Shell einfach mal durch ein kleines Demo-Programm zu ersetzen, welches wirklich nichts anderes macht, als eine Datei anzulegen, in sie zu schreiben und wieder zu schließen. Das sollte dann funktionieren. Gruß, Roland
Datum:
Hallo Roland, habe deinen Vorschlag befolgt und aus main.c alles aus der Minishell gelöscht bis auf "cat", "sync" und "write". Nur mit diesen Befehlen funktionierts, wie das Beispiel zeigt:
manuf: 0x1b oem: SM prod: SMI rev: 10 serial: 0x099da84f date: 7/7 size: 1017643008 copy: 0 wr.pr.: 0/0 format: 0 free: 1016709120/1017249792 > cat 2.txt 00000000: 20 0a 02 00 00 00 00 00 > write 2.txt 0 < jetzt funkt's < danke an Roland < > cat 2.txt 00000000: 6a 65 74 7a 74 20 66 75 00000008: 6e 6b 74 27 73 64 61 6e 00000010: 6b 65 20 61 6e 20 52 6f 00000018: 6c 61 6e 64 6e 20 52 6f > |
Sobald ich einen weiteren Shell Befehl, egal ob "ls" oder "touch" zusätzlich rein nehme, hängt sich das Prog wieder auf. Vielleicht liegts wirklich an der Grösse des Programms und dem Füllgrad des Flash obwohl AVR Studio nur 13.812 Byte und 84,3% meldet. Im Moment komm ich hier nicht weiter. Werd mich mal dran machen, Werte aus dem A/D Wandler in eine Datei zu schreiben, mal sehen, ob das klappt. Gruss Reinhard
Datum:
>Sobald ich einen weiteren Shell Befehl, egal ob "ls" oder "touch" >zusätzlich rein nehme, hängt sich das Prog wieder auf. Vielleicht liegts >wirklich an der Grösse des Programms und dem Füllgrad des Flash obwohl >AVR Studio nur 13.812 Byte und 84,3% meldet. Im Moment komm ich hier Jungs, nehmt doch einfach einen ATMega32. Nicht das Flash ist am Ende, es ist das RAM !
Datum:
Hallo Reinhard, Wie Holger schon angemerkt hat, geht es nicht ums Flash, da sind ja noch ein paar Kilobyte frei. Das RAM ist komplett belegt, und sobald der Stack in den Heap bzw. in den statisch allokierten Bereich reinwächst, gibt es Probleme. Dann kann alles passieren, vom merkwürdigen Verhalten bis zum Absturz. Zum Testen mag Dein Controller reichen, für die eigentliche Anwendung wirst Du aber ein Modell mit mehr RAM brauchen. Gruß, Roland
Datum:
holger wrote: > Jungs, nehmt doch einfach einen ATMega32. Nicht das Flash > ist am Ende, es ist das RAM ! Wohl wahr, das ist der wunde Punkt. 2k SRAM reichen zwar für Roland's Beispiel mit dem SD-Reader, für mehr aber nicht. Programmiert man eigene Sachen dazu erlebt man die gleichen merkwürdigen Effekte. Erst mit einem ATmega644 (4k SRAM) lief alles in meinem Fall so wie es sein sollte. Torsten
Datum:
Hallo, gibt's denn keine Möglichkeit das zu kontrollieren - entweder beim Compilieren/Linken vorher oder zur Laufzeit ? (btw. - der ATMega168 hat nur 1k !) Gruss Reinhard
Datum:
Hallo Reinhard! Nein, das geht in der Regel nicht, dazu wäre eine Laufzeitanalyse notwendig. Nur wenn das statisch allokierte RAM (also die Gesamtgröße aller globalen Variablen) bereits zu groß ist, kann das der Linker feststellen. Das hilft aber nichts, weil das RAM meist schon vorher durch den Stack (also lokale Variablen und die Parameter bei Funktionsaufrufen) und den Heap (sprich malloc()/free()) aufgebraucht wird. Ja, der mega168 hat nur 1kB, deshalb ist er ja so sehr am Limit. Gruß, Roland
Datum:
Hallo zusammen Hat jemand schon mit Roland Riegel's SD/MMC Software eine Micro SD Karte angesteuert? Versuche dies nämlich gerade. Die Initialisierung ist wahrscheinlich erfolgreich (muss ich noch genau untersuchen) aber es werden dann keine Disk Infos angezeigt. Gruss
Datum:
Hi Matthias, Ja, ich habe bei meiner Entwicklung sowohl Micro-SD (über Adapter) als auch normale SD-Karten benutzt. Eigentlich sollte es auch keine Unterschied, mal abgesehen von den üblichen Inkompatibilitäten, geben. Eine Micro-SD ist eine normale SD - halt nur kleiner. Gruß, Kai
Datum:
Wunderbar dann sollte das also klappen. Dann habe ich wieder einmal ein Fehler in meiner Schaltung :-) Danke für deine Hilfe dann werde ich noch ein bisschen weiter probieren. Gruss und schönes Wochenende
Datum:
Angehängte Dateien:@Roland Riegel, feine Sache, habe ATmega8L mit Miniversion ohne Probleme zum laufen gebracht. Jetzt bestehen ja richtige Möglichkeiten durch diese Software. Besten Dank Udo
Datum:
Hallo, Das sieht ja Prima aus. Moecht ich gerne auch ausprobieren! Könnte freundlicherweise jemand einen link zur Miniversion fuer Atmega8L posten. Irgendwie ist der Thread bezueglich Uebersichtlichkeit an seine Grenzen gestossen :) danke Gast
Datum:
Hallo Gast, ganz oben als erstes steht sie, vom Entwickler selbst. Dann nur noch alles genau lesen und schon geht es los.
Datum:
@Udo, Gast Bitte beachtet bitte, das in der allerersten Version diverse Fehler enthalten sind, die in dem neuesten Release behoben sind. Für möglichst kleinen Code also bitte nicht veraltete Ausgaben nutzen, sondern die jeweils neueste entsprechend abspecken. In den letzten fast zwei Jahren hat sich schließlich einiges getan... Gruß, Roland
Datum:
Angehängte Dateien:@Gast, als Anhang das Programm für ATmega8L. @R. Riegel, es ging aber um den Link und nicht um die Versionen. Zum Hardwareaufbau hat bestimmt jeder so seine eigenen Vorstellungen, ich finde es einfacher gleich alles mit 3,3V zu betreiben deswegen der ATmega8L, andere haben vielleicht schon Hardware mit 5V und wollen dann aber diese SD-Karten betreiben. Die letzte Version der Software steht doch bestimmt auf Deiner Webseite, habe jetzt aber auch nicht da nachgeschaut, gehe aber davon aus dass so etwas selbstverständlich ist. Dann finde ich es sehr wichtig so viel zu Lesen wie es geht um auch selbst zu entscheiden ob dass so alles stimmt wie es gerade beschrieben wird, wer weiß schon alles. Dann sind die eigenen Fehler sowieso die schlimmsten und dass geht nur mit Ausdauer am Projekt. Wie soll ich dass alles beschreiben? Udo
Datum:
Hi, ich bin endlich dazu gekommen an meiner Cocktailmaschine zu werkeln. Ich habe bereits ein rudimentäres Programm mit 3 Tastern, LCD-Display zur Auswahl auf Basis eines Atmega16 am laufen. 2 komplette 8 Bit Ports wollte ich wohl für die Pumpen bzw. Magnetventile reservieren. Leider reicht mir der EEPROM zum speichern von Rezepten nicht aus, da bekomm ich maximal 20 Rezepte untergebracht weil ich speichere die Namen der Cocktails als Strings mit maximal 18 Zeichen für das 4*20 LCD. Zur Zeit nutze ich den Programmspeicher dafür, was ich aber sehr unfexibel finde. Ich ich will nicht bei jeder Änderung den Chip neu programmieren und da bin ich über diesen Beitrag gestolpert. Ich finde die Idee mit der SD Karte recht gut, weil dann kann ich die Rezepte am PC zusammenfriemeln und darauf speichern, der Atmega muss sie dann nur lesen können. Jedoch benötige ich nich wirklich ein Dateisystem wie FAT16 ... ich bräuchte auch nur eine Datei mit meinem eigenem Datenformat. Ich würde dann also nur die SW_RAW routinen verwenden und quasi mein eigenes Dateisystem, d.h. einfach nur ein datenstream in einem bestimmtem Format darauf speichern und auf dem PC ein Programm schreiben welches die Daten auf der SD karte in diesem Format speichert. Soweit so gut. Grad mal geguckt es gibt ja fasst nur noch Karten die mindestens 1GB Speicherkapazität haben, soviel brauche ich nun auch wieder nicht, mir würde sogar 1MB dicke reichen. Jetzt wollte ich mal fragen ob es da nicht eine bessere Lösung gibt. Außerdem meine ich hier gelesen zu haben, dass man die Daten nur in 512byte Blöcken lesen kann, heißt das jetzt das ich immer mindestens 512byte in einem rutsch lesen muss? Danke im Vorraus.
Datum:
Hallo Jan, Ob du SD-Karten nutzt oder nicht, musst letzten Endes Du entscheiden. Beachte allerdings, dass der Hardwareaufwand relativ gering ist und der Speicher pro MB unschlagbar billig, verglichen mit externen EEPROMs oder Flash-Chips. In der Regel werden die SD-Karten 512-Byte-weise angesprochen, ja. Wenn Du meine sd_raw-Routinen verwendest, ist das aber wurscht, da diese einen wahlfreien Zugriff mit beliebiger Blockgröße ermöglichen. Gruß, Roland PS: Wenn Du die Strings mit dynamischer Länge ablegst und mit einem Null-Byte abschließt, kannst Du auch ein bisschen Platz sparen.
Datum:
Angehängte Dateien:Hallo,
ich habe meine Schaltung jetzt auch ans laufen bekommen, ein kleines
Verstänissprob. bleibt. Wenn ich mit
...
uint8_t buffer[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08};
fat16_write_file(fd, buffer, 9);
...
fat16_close_file(fd);
...
Auf die Karte schreibe werden 2 Byte und nicht 9 geschrieben. Rufe ich
vorher:
fat16_resize_file(fd, 9);
auf passt es.
Ist das ein zu erwartendes Verhalten?
An dieser Stelle auch mal ein herzliches Dankeschön an Roland für die
klasse lib.
Gruß
Malte
Datum:
Hallo Malte, Normalerweise sollten da schon neun Bytes geschrieben werden. Was gibt denn fat16_write_file() zurück? Immer den Rückgabewert mit der Anzahl zu schreibender Bytes vergleichen! Sonst kann man sich nie sicher sein, dass wirklich alle Bytes geschrieben wurden. [1] Ansonsten: Benutzt Du SD_RAW_WRITE_BUFFERING? Wenn ja, musst Du vor dem Entfernen der Karte sd_raw_sync() ausführen! [2] Gruß, Roland [1] http://www.roland-riegel.de/sd-reader/doc/group__f... [2] http://www.roland-riegel.de/sd-reader/doc/group__s...
Datum:
Hallo Roland, ich gebe die anzahl der geschriebenen Bytes auf dem Display aus. Das passt soweit. Ich dachte sd_raw_sync() ist nicht erforderlich wenn ich die Datei mit vor dem Entfernen mit fat16_close_file(...) schliesse. Dann hatte ich gestern aber noch weitere seltsame Effekte. Bin jetzt aber nicht ganau in der lage diese richtig zu beschreiben. Ich denke ich schau mal ob da nicht der Stack zu gross wird. Gruß Malte
Datum:
Hallo Malte, Doch, in den bisherigen sd-reader-Versionen ist der Aufruf von sd_raw_sync() immer manuell auszuführen. Am besten beispielsweise vor längeren Zugriffspausen, wenn die Wahrscheinlichkeit hoch ist, dass die Karte abgezogen wird. Ich hatte auch schon dran gedacht, sd_raw_sync() beim Aufruf einiger FAT-Funktionen automatisch auszuführen. Vielleicht werde ich das mal implementieren. Wenngleich das in einigen Zugriffsszenarien den Puffereffekt zumindest teilweise zunichte machen könnte... Nebenbei bemerkt glaube ich nicht, dass sd_raw_sync() bei Dir das Problem ist, da die ersten zwei Bytes ja geschrieben werden. Die restlichen sieben sollten dann ja gleichzeitig in dem gleichen Sektor landen. Zu Deinem Fehlerbild fällt mir im Moment außer dem von Dir erwähnten RAM-Mangel auch nichts passendes ein. Welchen AVR nutzt Du eigentlich? Gruß, Roland
Datum:
Hi Roland, ich verwende einen ATMEGA128. Der ist allerdings mit knapp 3500 bytes sram recht gut gefüllt. Stack muss dann noch in die verbleibenen 500 bytes passen. Dynamischen Speicher über malloc oder die builtin Funktionen verwende ich nicht. Am Anfang der oben angehängten Routine habe ich noch 187 bytes Speicher frei. Mit sd_raw_sync() scheint es jetzt soweit zu funktionieren. Danke Gruß Malte
Datum:
Hi, as I see there is a lot of expertise (which I am lacking) in this forum I would kindly ask you whether it would be possible to write a simple "user fiendly library" based on Roland's code which is easy to use by beginners as well - e.g.: sd_init() sd_open(&filename)(if it does not exist than create) sd_date(&filename,year,day,..min,sec) (time stamp) sd_write(&filename,*buffer) sd_read(&filename,*buffer) sd_append(&filename,*buffer) sd_delete(&filename) sd_close(&filaname)... ... where buffer is a string[40] etc., so you printf(string,"%u...",temp). filename is a string ( e.g. "\temp\new\measure1.txt") So one can easily open a file and write data there. I would say it is a half hour work for an expert to make this great fat16 library available for an "standard" user who wants just write temperature or some data into files.. pito
Datum:
@pito, I will not provide you with code, because all you need is more or less already available with the main.c example application from the sd-reader source. You just have to write up some wrapper functions into which you put the example code: sd_init: sd_raw_init(), partition_open(), fat16_open() sd_open: fat16_get_dir_entry_of_path(), fat16_open_file() sd_date: fat16_get_file_modification_date/time() sd_write: fat16_write_file() sd_read: fat16_read_file() sd_append: fat16_seek_file(), fat16_write_file() sd_close: fat16_close_file() sd_delete: fat16_delete_file() That would be it. You might also want to look at the mega-eth project (http://www.roland-riegel.de/mega-eth/), where I reused the sd-reader code and wrote something which equals your sd_init(). Greetings, Roland
Datum:
Hallo, ich bin seit einiger Zeit dabei Daten auf einer Speicherkarte abzulegen. Meine ersten Versuche liefen ohne FAT Dateisystem und nur mit ansteuerung der Sektoren. Ich habe dafür das Beispiel von Ulrich Radig genutzt. Ich konnte damit ohne Probleme speichern. Nun wollte ich jedoch etwas mehr probieren und mal das FAT16 System von Roland Riegel testen. Jedoch hab ich da so ein paar Probleme. Ich nutze das Pollin-Board mit einem ATmega32 (mit internem Takt [8MHz]) und die Speicherkartenansteuerung ist eine Komplettlösung der Firma E-LAB. Des Weiteren nutze ich MMC-Speicherkarten, weil in den Slot keine SD-Karten passen. Es treten schon Probleme auf, wenn die "Fabrikdaten" ausgelsen werden. Beim letzten Punkt, wo der freie und belegte Speicherplatz angezeigt werden soll, hängt sich das Programm auf und es geht nicht weiter. Kommentiere ich diese Zeile aus, läuft es erstmal. Ich kann auch ohne Porbleme den Inhalt mit dem Befehl "ls" auslesen. Jedoch kann ich keine neuen Dateien erstellen oder in vorhandene Textdateien hineinschreiben. Ich wollte das ganze System als eine Art Datenlogger nutzen. Was mir auch noch aufgefallen ist, das manche Karten gar nicht erst erkannt werden. Ich hoffe ihr könnt mir bei diesem Problem weiter helfen. gruß Thomas
Datum:
Roland Riegel wrote:
..
> (http://www.roland-riegel.de/mega-eth/
Wow. Gratuliere zum neuen Projekt! Sieht sehr gut aus.
BTW: Hast es hier ja garnicht vorgestellt.. ;)
Torsten
Datum:
@Torsten, Danke, aber vorgestellt habe ich es doch :) Beitrag "Erweiterbares Ethernetboard mit MMC/SD-Slot und USB" Gruß, Roland
Datum:
Guten Morgen, ich hab gestern noch ziemlich lange probiert das Problem zu finden. Hab noch mehr Speicherkarten getestet und sogar mal ne SD-Micro + Adapter ausprobiert. Irgendwie komme ich da nicht weiter. Hab hier nochmal den Link von dem Speicherkartenmodul: http://www.e-lab.de/components/cf_and_co.html Es handelt sich dabei um das "MMC Card Interface for MINI-SD". Das Pollinboard sollte, so denke ich, einigermaßen bekannt sein: http://www.pollin.de/shop/shop.php Am Quellcode kann es ja eigentlich nicht liegen. Und meine Speicherkarten waren alle 128MB groß oder kleiner. Damit sollten also auch keine Probleme entstehen. Was mich am meisten wundert ist, dass bei den Karten, die funktionieren, nur die Lesebefehle ohne Probleme klappen. Bei den Schreibbefehlen bleibt er immer hängen. Nutze zum Testen WindosXP mit Hyperterminal bzw. Hterm. Vielleicht hat ja jemand schon so ein ähnliches Problem gehabt?! gruß Thomas
Datum:
Hallo Thomas, Mit den paar Angaben die Du machst kann man nur raten. Überprüfe Deine Konfiguration in sd_raw_config.h. Finde auch mal selbst heraus, wo genau er hängen bleibt. Füge vor und hinter jeden zu untersuchenden Funktionsaufruf Debug-Ausgaben ein, ebenso in den aufgerufenen Funktionen selbst. Versuche so einzukreisen, bis wo er kommt. Versuche doch erst mal den Sektorzugriff über sd_raw_read() und sd_raw_write() zum Laufen zu bringen, erst dann solltest Du über FAT16 nachdenken. Gruß, Roland
Datum:
@ Roland: Also die Sende und Empfangsfunktionen ohne FAT16 funktionieren ohne Probeme. Diese gingen ja auch schon, als ich das Projekt von Ulrich Radig verwendet hatte. Um zu überprüfen, wo er hängen bleibt, lass ich mir vor den Funktionen immer Meldungen über die Uart ausgeben. Und wie gesagt, er bleibt ja schon dann hängen, wenn er den freien Speischerplatz angeben soll. Aber ich werde jetzt erst einmal alle anderen, auch nicht genutzen Funktionen überprüfen und nochmal testen, was passiert, wenn ich den Code nur auf die Schreibfunktion begrenze. Was mich aber mal noch interessiert, ist die Frage zu den Speicherkarten. Sind da schon Probleme bekannt, dass es mit einigen Typen Probleme gibt? Ich habe sie ja alle unter Windows mit FAT formatiert. gruß Thomas
Datum:
Hallo Thomas, Selbst habe ich meinen Code nur mit SD-Karten ausprobiert, von anderen habe ich aber auch noch nichts über Probleme mit MMC-Karten gehört. Zum Hängen: Vermutlich hängt er in einer der while(1)-Schleifen in sd_raw.c fest, weil die Karte aus irgendeinem Grund nicht mehr (richtig) antwortet. Du könntest mal die Datei sd_raw.c aus mega-eth verwenden, da habe ich diese Warteschleifen zeitlich schon begrenzt. Überhaupt sind noch einige Rückportierungen von mega-eth nach sd-reader in der Warteschleife. Gruß, Roland
Datum:
Roland Riegel wrote: > Danke, aber vorgestellt habe ich es doch :) > Beitrag "Erweiterbares Ethernetboard mit MMC/SD-Slot und USB" Opps. Das habe ich irgendwie übersehen... Torsten
Datum:
Hallo allerseits, ich wollte jetzt mal wieder meinen neuen Stand posten. Also, ich kann jetzt auf die Speicherkarten schreiben und lesen mit FAT. Das Problem liegt dabei an dem Root-Verzeichnis. Dort hängt er sich immer auf. Erstelle ich jedoch Unterordner, läuft alles ohne Probleme. Dort kann ich dann, wie von mir gewünscht,Ordner erstellen, Dateien erstellen, dort hinein schreiben und die Dateien dann auf einem PC öffnen. Das Problem liegt jetzt aber daran, dass ich sie nur unter Linux lesen kann. Windows gibt immer sie Fehlermeldung, dass die Datei beschädigt ist. Ich erstelle .txt dateien und habe es mit Notepad und Editor probiert. Beides ohne Erfolg. Hat jemand auch so etwas bemerkt? Woran könnte das liegen? Damit wär mir schon gut geholfen. Vielen Dank. gruß Thomas
Datum:
Hallo Thomas,
Du hast schon die neueste sd-reader-Version? Ältere Ausgaben hatten
Fehler wie von Dir beschrieben, die aktuellste eigentlich nicht. Führst
Du vor dem Entfernen der Karte ein sd_raw_sync() ("sync" auf der
Kommandozeile) aus?
(Hoffentlich komme ich demnächst endlich mal dazu, einige
Aktualisierungen zu veröffentlichen.)
Gruß,
Roland
Datum:
Angehängte Dateien:So, heute habe ich die versprochenen Verbesserungen auf meiner Homepage veröffentlicht und hänge sie jetzt auch wieder an dieses Posting an. Die Änderungen u.a.: - Neuer Befehl "init" initialisiert und öffnet die Karte neu. - Viel höhere Geschwindigkeit beim Durchsuchen bzw. Auflisten von Verzeichnisinhalten. - Suche in Verzeichnissen mit mehr als einem Cluster korrigiert. - Lesen von Verzeichniseinträgen korrigiert, die über eine Clustergrenze reichen. - Breche bei zu langen Dateinamen nicht den ganzen LFN-Eintrag ab, sondern lasse nur einzelne Zeichen weg. - Reduktion der Codegröße durch zentralisierte Berechnung der Clusteradressen. - Einige andere Korrekturen und Optimierungen. Viele Grüße, Roland
Datum:
Guten Tag zusammen Ich habe eine kurze Frage zur File Erstellung bei bei Rolands Sd-Reader. Ist es normal das ich ein File z.B test.txt nur in einem Ordner ablegen kann? Zuerst wollte ich es direkt auf der root Partition ablegen aber dies funktionierte leider nie. Also habe ich einen Ordner erstellt, in diesem anschliessend das File abgelegt und siehe da es funktioniert. Ich bin mir ziemlich sicher das ich irgendwo noch einen Fehler mache. Aber ich weis leider momentan nicht wo. Ich hoffe jemand kann mir ein paar Tipps geben. Gruss Mathias
Datum:
Hallo Mathias, Doch, das Anlegen von Dateien im Wurzelverzeichnis sollte ohne Probleme funktionieren, schließlich kann man dort ja auch Verzeichnisse anlegen und das ist im Prinzip auch nichts anderes. Wie hast Du es denn probiert, von der UART-Kommandozeile aus oder mit einem eigenen Programm? Kannst Du im letzten Fall den Quelltext bzw. einen Ausschnitt davon posten? Gruß, Roland
Datum:
Ja da hast du recht, ich habe bereits selbst einmal eine Datei im Wurzelverzeichnis angelegt. Dies war allerdings mit dem UART-Kommandozeilen Programm. Nun habe ich ein eigenes Programm versucht zu erstellen und dort hatte ich allerdings Probleme. Was allerdings komisch ist, ist das ich einen Ordner anlegen kann aber keine Datei. Hier ein kleiner Teil des Codes:
struct fat16_dir_struct* dir = 0; while (1) { if (Taster_Enter_pos_F) { struct fat16_dir_entry_struct file_entry; fat16_create_file(dir, "test.kml", &file_entry); sd_raw_sync(); } } |
Ich danke dir für deine Hilfe, wirklich klasse Support. Gruss
Datum:
Das kann so auch nicht funktionieren, da Du fat16_create_file() mit dem ersten Argument einen Null-Pointer übergibst. Schau mal in der main.c vom sd-reader nach, dort wird das Wurzelverzeichnis geöffnet. Dieses Handle auf das Wurzelverzeichnis übergibst Du dann fat16_create_file(), dann funktioniert es auch. Woher sonst sollte die Funktion sonst wissen, in welchem Verzeichnis Du die Datei erzeugen willst? Gruß, Roland
Datum:
Hi Roland, does the cd command in the newest sd-reader_source_20080608 work? > mkdir rrr > ls rrr/ 0 > cd rrr directory not found: rrr Gruss, Pito
Datum:
Hi, cd works until you provide "init". Than cd stops to work.. Pito
Datum:
Hallo! Ich habe hier eine sagenhafte 8 MB(!)-SD Karte. Erst funktionierte sie nicht, bis ich die Abfrage auf
if(data_cluster_count < 4085 || data_cluster_count >= 65525) |
gefunden und das entsprechende "< 4085" auskommentiert habe. So viele
Cluster gibt es anscheinend auf einer 8MB-Karte nicht.
Jetzt habe ich aber das Problem, dass ich auf der frisch formatierten
Karte eine Datei anlegen will (und dort auch etwas reinschreibe) und die
Datei dann in Windows aber nicht gelesen werden kann (über das
UART-Interface geht´s aber).
Ich führe dann ein CheckDisk ("Auf Fehler überprüfen") durch, was die
Datei (meistens) wieder herstellt.
Danach kann ich auch weitere Dateien anlegen, die dann problemlos
gelesen werden können.
Hier noch die Karteninfo:manuf: 0x01 oem: PA prod: S008B rev: 41 serial: 0x39d181e1 date: 9/3 size: 6799360 copy: 0 wr.pr.: 0/0 format: 0 free: 6725632/6760448 |
Könnte das Problem nur an der geringen Größe der Karte liegen? Gruß Markus
Datum:
Hallo Markus, Wie formatierst Du die Karte denn? Vielleicht legt Windows bei der geringen Größe ein FAT12- und kein FAT16-Dateisystem an. Das würde auch erklären, warum Du die Bedingung bzgl. der Clusteranzahl auskommentieren musstest (die ja durchaus ihren Sinn hat, denn bei FAT12 kann es netto eben bis zu 4084 Cluster geben). Gruß, Roland
Datum:
Hallo Roland! Hast Recht. Windows legt eine FAT12 an (hab ich mir mit "WinHex" angeschaut). Nur: Wie kann ich trotzdem ne FAT16 formatieren? Hab mittlerweile eine größere Karte (256MB) geliehen, jedoch bleibt diese in der Initialisierung (fat16_open.... partition/device_read irgendwo hängen). Muss das nochmal genauer analysieren, wo es hakt. Gruß & Danke für deine Hilfe Markus
Datum:
Hallo, ich bin´s nochmal... komme gerade nicht so richtig weiter. Er bleibt an dieser Stelle hängen:
uint8_t fat16_read_header(struct fat16_fs_struct* fs) { if(!fs) return 0; struct partition_struct* partition = fs->partition; if(!partition) return 0; /* read fat parameters */ uint8_t buffer[25]; uint32_t partition_offset = partition->offset * 512; --------------------------------------------- if(!partition->device_read(partition_offset + 0x0b, buffer, sizeof(buffer))) { return 0; } |
Bis zu der "---------" kommt er, aber in der device_read-Funktion kommt er nicht mehr an. Wenn ich das richtig sehe, müsste er ja in struct partition_struct* partition_open(... ankommen. Kommt er aber nicht. Bin etwas ratlos gerade. Mit eine 8MB-Karte läuft alles. Gruß Markus
Datum:
So, es geht! Hab allerdings einen andere "Formatter" benutzt (nicht Windows, sondern "SD Formatter 2.0" von Panasonic(?)). Damit geht´s ohne Probleme und auch Windows kann die Dateien einwandfrei lesen. Irgendeine Idee?
Datum:
Hallo Zusammen,
ich benutze die USART Schnittstelle vom AT90USB1287 in SPI Master Mode,
um DAB(digital audio broadcast) Daten auf der SD-Karte zu speichern.Beim
Debuggen wird in der Funktion "struct fat16_fs_struct* fs =
fat16_open(partition);" die folgende Zeile nicht richtig ausgeführt
"if(!fat16_read_header(fs))".In dieser Funktion ruft die
Zeile:"if(!partition->device_read(partition_offset + 0x0b, buffer,
sizeof(buffer)))" die Funktion "uint8_t sd_raw_read(uint32_t offset,
uint8_t* buffer, uint16_t length)" auf.In dieser Funktion(sd_raw_read)
hängt das Programm an der folgenden Stelle:
/* wait for data block (start byte 0xfe) */
while(sd_raw_rec_byte() != 0xfe);
Das ist die kritische Stelle.Die Funktion sd_raw_rec_byte() sieht so
aus:
uint8_t sd_raw_rec_byte()
{
/* send dummy data for receiving some */
/*SPDR = 0xff;
while(!(SPSR & (1 << SPIF)));
SPSR &= ~(1 << SPIF);
return SPDR;*/
// Send dummy data for receiving some.
UDR1 = 0xff;
// Wait for empty transmit buffer.
do {} while( (UCSR1A & (1<<UDRE1)) == 0 );
// Wait for transfer to complete and return received value.
do {} while( (UCSR1A & (1<<RXC1)) == 0 );
return UDR1;
}
Weiss jemand woran es liegt, dass das Programm an dieser Stelle hängen
bleibt? Da ich USART in Master SPI Mode benutze habe ich einige Stellen
in den Datei im Anhang verändert. Vielleicht hift es bei der
Fehlersuche.
Ich bedanke mich im voraus für Ihre Hilfe.
Gruss
niketchana
Datum:
Hallo, jetzt geht´s. Das war ein Problem der Formatierung.Anscheinend formatiert Window mit FAT12.Ich habe die Karte mit dem "SD Formatter 2.0.0.3 von Panasonic" formatiert und schon geht alles. niketchana
Datum:
Hallo, hat sich in diesem Zusammenhang schon mal jemand mit Gnu unzip beschäftigt? Ich hab das Problem das ich eine Gnu gezippte Datei auf einer SD-Karte auslesen und gleichzeitig entpacken will. Danke
Datum:
Nein, ich zumindest nicht. Warum ist die Datei denn gepackt, bzw. muss sie das denn sein? Die Karten sind doch eh groß genug. Ich würde in diesem Zusammenhang auch erst mal mit zlib experimentieren, das sollte besser portierbar sein. Habe allerdings keine Ahnung, wieviel Flash der Algorithmus belegen würde. Es gibt jedoch schon ein Beispiel namens "minizip", das den ZIP-Header interpretiert. Alternativ das GZ-Format verwenden, das ist einfacher. Gruß, Roland
Datum:
Das Flash im Prozessor leider nicht. Ich brauche eh das Gnu Format. Ich hab mich mal bei der Busybox umgeschaut. Vielleicht komme ich damit weiter. Danke, für die Antwort
Datum:
Hi gents, let me ask you kindly following: I am running the latest sdreader demo and when writing a text file to the 512MB SD card (atmega32, 11MHz, 115k 8n1)via the write command (realterm terminal - dump file to port) the writing speed is aprox 400-500byte/sec. Is this a typical speed or is there something wrong with my setup? Thanks, pito.
Datum:
The sd-reader text console accessible via UART is not meant to be used as a data interface during normal operation, the same applies to the circuit itself. It is for debugging and test purposes only. To achieve proper speed, integrate the circuit and the sd_raw/partition/fat16 code into your application. Depending on the configuration and the size of the buffers used, several dozens of kBytes/sec are possible. Greetings, Roland
Datum:
Hi Roland, thanks! I do consider your test code as very useful for us - beginners, to play with the sdcard and FAT16.. and for diagnostic purposes too.. I've tried several other implementations, however this one is my favorite as there is the test console offered! Let me ask you kindly whether would be possible for you (or somebody from community who understand the implementation well) to insert a simple command (e.g.copy) into the sdreader test console for testing the copying of files e.g.: copy file1 file2 (files of any size) in the actual directory you moved in via cd command. It will be very useful for experimenting with setups/buffers etc and testing the cards. Thanks a lot, Pito
Datum:
No, I will not implement this.
You can do this yourself, it's quite simple. Use fat16_open_file(),
fat16_read_file(), fat16_close_file() for the file which to read, and
fat16_create_file(), fat16_open_file(), (fat16_resize_file(),)
fat16_write_file(), fat16_close_file() for the file to write.
See
http://www.roland-riegel.de/sd-reader/doc/group__f...
for the documentation of the FAT16 file handling.
Greetings,
Roland
Datum:
Diese Fragen kenn ich von der Arbeit. g Da wird dann debug-code ganz schnell mal vergewohltätigt.
Datum:
Ok, alles klar.. Ich dachte nur - fals man schon das ganze Geschichte drin in einen email steckt, wird das schon vielleicht bischen einfacherer und schneller das Code in den sdreader implementieren zu koennen (:-). Aber Ich verstehe ganz gut (da ich auch von Arbeit solche miesse triks kenne) dass man schon andere Sachen zu tun haette.. Ich bin auch nicht besonders geil die Sachen die schon einwandfrei laufen nur so mirnix dirnix anfassen zu muessen (auch wenn jemand solche bereitschaft "Kundenorientation" nennt). Nun - was mir in den "debug code" fehlt ist eine Moeglichkeit die reine Transfergeschwindichkeit unter bestimmten Bedinungen einfach zu beobachten. Und dafuer is der "copy" Befehl sehr gut geeignet, meine Ich. Man braucht nix anders. Niemand bietet Euch (die Experten) ein MMC DOS zu schreiben.. Gruss, Pito
Datum:
Angehängte Dateien:Hallo allerseits, Heute nach längerer Pause mal wieder ein Update. Zwei wesentliche Features sind dazugekommen: - Unterstützung für SDHC-Karten. - Unterstützung für FAT32. Insgesamt heißt dass, das jetzt auch Karten mit mehr als 2GB genutzt werden können. Da die Neuerungen einiges an Flash mehr brauchen ist für die Beispielanwendung mindestens ein ATmega328 erforderlich. Da ich diesen noch nicht habe (getestet wurde das ganze mit mega-eth), sind die neuen Features standardmäßig abgeschaltet. Zum Einschalten SD_RAW_SDHC in sd_raw_config.h auf 1 setzen. Wie immer ist die Doku im ZIP enthalten, findet sich zusammen mit einem Patch zur vorhergehenden Version aber auch auf der Homepage unter http://www.roland-riegel.de/sd-reader/ Viele Grüße, Roland
Datum:
Hallo Roland, Das sind sehr gute Neuigkeiten. Danke dass Du uns Deinen Code zur Verfügung stellst! Mehr Flash ist (bei mir) kein Problem. Wie sieht es aber mit dem SRam aus - wird mehr gebraucht oder bleibt alles beim alten? Torsten
Datum:
Hallo Torsten! Die Datenstrukturen haben sich nicht wesentlich geändert, allerdings sind einige Elemente größer geworden, da mit FAT32 die Clusternummern und mit SDHC die Offsetadressen breiter werden. Dies ist mit den Typedefs cluster_t bzw. offset_t geregelt. Ein kleiner Überblick: - geöffnetes Dateisystem: +12 Bytes - directory entry: +6 Bytes - geöffnete Datei: +12 Bytes (inkl. dir entry) - geöffnetes Verzeichnis: +8 Bytes (inkl. dir entry) Beim Dateisystem könnte man eventuell noch vier Bytes rausholen, insgesamt sind die Zuwächse aber eher human. Viele Grüße, Roland
Datum:
Hallo Roland, Danke für den kurzen Überblick. Der Mehrverbrauch an SRam ist wirklich zu verschmerzen wenn man sich vor Augen hält das nun Fat32 und Sdhc unterstützt werden. Bei der nächsten Gelegenheit werde ich alles mal testen und Dir ein Feedback geben. "Keep up your good work!" Torsten
Datum:
Ok, bin gespannt ob es auf Anhieb funktioniert. Nochmal zum RAM-Verbrauch: Der Stack wird auch etwas größer sein als zuvor, da mit den breiteren Datentypen natürlich gearbeitet werden muss. Wieviel das genau ausmacht, kann ich auf Anhieb aber nicht sagen. Gruß, Roland
Datum:
@Roland Riegel Hallo Roland, ein kleines Problem. Ich verwende deine FAT (sd-reader_source_20081121.zip) für meinen AVR Webserver (basiert auf deinem ;-)). Das Problem ist... Bei Datei- bzw. Verzeichnisnamen welche in das 8.3 Format passen wird der Name offenbar immer in Großbuchstaben gesucht/angezeigt, obwohl diese unter Windoze oder Linux mit Kleinbuchstaben auf die SD kopiert wurden (und auf diesen OSs auch so angzeigt werden). Da funktionieren natürlich die Links auf dem Webserver nicht mehr :-( Hast du ein Idee wo ich etwas ändern muss? Danke schon mal Werner P.S. raw_entry[11] == 0x0f Was steckt dahinter?
Datum:
> P.S. raw_entry[11] == 0x0f > Was steckt dahinter? Selbst beantwortet: Attribute "Read-only, System, Hidden, and Volume" == LFN Entry
Datum:
Hallo Werner, Bei 8.3-Namen schreiben die Betriebssysteme keine LFN-Namen ins Verzeichnis (im Unterschied übrigens zum sd-reader). Die 8.3-Namen werden immer in Großbuchstaben abgespeichert. Soweit ich mich erinnere gibt es aber ein paar Bits, die angeben, ob diese Namen als "GROSS", "klein" oder "Gemischt" interpretiert werden sollen. Ich werde nochmal danach suchen und schauen, ob und wie einfach man das implementieren kann. Gruß, Roland
Datum:
Hallo Roland, als "Workaround" abe ich eben die betreffenden strcmp in strcasecmp geändert. Funktioniert soweit, sollte aber nicht die engültige Lösung sein. Danke nochmal für den wirklich sauber und glasklar strukturierten Code. Endlich mal jemand der seinen Quelltext so formatiert wie ich ;-) fühle mich darin "Zuhause". Gruß, Werner
Datum:
Angehängte Dateien:Servus Werner, Freut mich wenn Dir mein Code gefällt. Probiere mal den angehängten Patch. Bei mir zeigt er damit in Tests die korrekte Groß-/Kleinschreibung an. Viele Grüße, Roland
Datum:
Roland
> klappt hervorragend.
Sieht so aus als wenn eine neue Version fällig ist. ;) Bin selbst noch
nicht zum testen gekommen, könnte noch eine Weile dauern..
Torsten
Datum:
@Werner Ok schön, habe die Änderung übernommen, sie wird dann in der nächsten Version enthalten sein. @Torsten Nö, deswegen mache ich nicht gleich ne neue Version. Es tritt ja nur bei 8.3-Namen auf und auch nur, wenn die Dateien auf dem PC erzeugt werden. Und wen es doch stört, der kann ja den Patch von oben verwenden. Viele Grüße, Roland
Datum:
Hallo ich hab da mal ne Frage bezüglich schreiben auf die SD Karte. Habe eine 2 GB SD Karte auf welcher ich eine Datei erzeuge und in diese Datei Text schreibe. Das funktioniert auch so, aber der letzte Schreibvorgang auf die Karte geht jedoch immer verloren, bzw wird nicht gespeichert. Mach ich was falsch, oder muss ich abschliessend noch eine Funktion aufrufen damit die Daten abgespeichert werden? Übrigens wer SD Karten Slots mit Auswurfmechanismuss benötigt, kann diese gerne von mir zum Versandkostenpreis haben. Sind SMD Kartenslots von Mainboards voll Funktionstüchtig und mit allem Drum und drann.
Datum:
Wird die Datei denn vor dem entnehmen der Karte geschlossen?
fat_close_file(sd_file); fat_close_dir(sd_dd); fat_close(sd_fs); partition_close(sd_partition); |
Datum:
Also ich machs eigentlich so wie es Testfile von Roland gestanden hat:
char* command = buffer;
strcpy(command, "Test.txt");
struct fat_dir_entry_struct file_entry;
int8_t result = fat_create_file(dd, command, &file_entry);
if (result)
{
struct fat_file_struct* fd = open_file_in_dir(fs, dd,
command);
if(!fd)
{
uart_puts_p(PSTR("error opening "));
uart_puts(command);
uart_putc('\n');
continue;
}
char* offset_value = command;
int32_t offset = strtolong(offset_value);
if(!fat_seek_file(fd, &offset, FAT_SEEK_SET))
{
uart_puts_p(PSTR("error seeking on "));
uart_puts(command);
uart_putc('\n');
fat_close_file(fd);
continue;
}
/* write text to file */
strcpy(buffer, "Text1\r\n");
uint8_t data_len=strlen(buffer);
if(fat_write_file(fd, (uint8_t*) buffer, data_len) !=
data_len)
{
uart_puts_p(PSTR("error writing to file\n"));
break;
}
strcpy(buffer, "Text2\r\n");
data_len=strlen(buffer);
if(fat_write_file(fd, (uint8_t*) buffer, data_len) !=
data_len)
{
uart_puts_p(PSTR("error writing to file\r\n"));
break;
}
strcpy(buffer, "ENDE\r\n");
data_len=strlen(buffer);
if(fat_write_file(fd, (uint8_t*) buffer, data_len) !=
data_len)
{
uart_puts_p(PSTR("error writing to file\r\n"));
break;
}
fat_close_file(fd);
}
fat_close_dir(dd);
/* close file system */
fat_close(fs);
/* close partition */
partition_close(partition);
Wenn ich dann nachschau in der Datei auf der SD Karte, dann seh ich nur
die ersten zwei Zeilen stehen:
Text1
Text2
Es fehlt jedoch die dritte Zeile :
also ENDE
Jemand ne Idee was ich da falsch mache?
Datum:
Hallo Habe einen ATMega 64 mit 16MHz Clock. Als erstes habe ich bemerkt, dass bei meinem Mega64 Clk/4 mit SPI2x nicht funktioniert. (Also halber CLK) SCK ist mit CLK/4 fast gleich langsam wie CLK/128. Also hab ich CLK/16 mit SPI2x, also CLK/8 verwendet. Habe die Funktionen wie schon im vorherigen Post gezeigt aufgerufen. Habe mal mit einem Oszi versucht zu messen wie lange der schreibvorgang dauert. Also mit CLK/128 dauert das schreiben von etwa 25 Zeichen etwa 250 Millisekunden. Mit CLK/8 dauert es immer noch etwa 20-30 Milliskunden. Die Zeiten variieren komischerweise um 5 ms! Ich meine, mir kommt es bei einem Datenlogger nicht auf Geschwindigkeit an, aber es erhöht den stromverbrauch des Datenloggers, weil die CPU weniger lang im Sleep Modus ist. Kann mir hier jemand sagen, ob die Werte stimmen könnten, oder ob das normalerweise viel viel schneller geht.
Datum:
Also nur zur Info: Sollte jemand mal das selbe Problem mit dem Schreiben von Daten auf die Karte haben. Und der letzte ausgeführte Schreibbefehl wird scheinbar nicht ausgeführt, also die Daten sind nicht auf der Karte gespeichert worden, dann liegt das am SD_RAW_WRITE_BUFFERING welches im sd_raw_config.h einzustellen ist. Der ist bei aktivierten Schreibsupport automatisch eingeschaltet. Leider wird geht das schreiben im Mittel dadurch aber auch langsamer von statten.
Datum:
Hallo Klaus, Wenn bei Dir die letzten Bytes nicht mehr auf die Karte geschrieben werden, liegt das daran, dass Du bei eingeschaltetem SD_RAW_WRITE_BUFFERING vor dem Abstecken der Karte kein sd_raw_sync() aufrufst. Du solltest, genauso wie am PC auch, die Karte nicht während laufender Schreibvorgänge abziehen. Weder werden dabei die Daten korrekt gesichert, noch ist danach die Integrität des Dateisystems sichergestellt. Sehe also einen Weg vor, die Karte ohne Probleme abzustecken, z.B. durch - eine LED, die anzeigt, ob alle Schreibvorgänge abgeschlossen wurden - einen Taster, der vor dem Abziehen sd_raw_sync() aufruft. Bzgl. der Schreibgeschwindigkeit: Öffne und schließe bei den einzelnen Schreib-/Lesevorgängen die Datei nicht immer neu. Benutze am Anfang einmal fat_open_file(), und vor dem Abstecken der Karte fat_close_file() (und sd_raw_sync()), dazwischen nicht mehr. Bedenke auch, dass das Anhängen an eine Datei sehr aufwändig ist, da hier immer auch der Verzeichniseintrag und evtl. die FAT aktualisiert werden müssen. Stattdessen solltest Du die Datei zu Beginn auf eine bestimmte Größe aufblähen (fat_resize_file()), dann an den Anfang springen (fat_seek_file()) und von dort aus schreiben. Bedenke auch, dass das Schreiben weniger großer Blöcke schneller ist als das Schreiben vieler kleiner Blöcke. SPI mit halbem MCU-Takt (also CLK/4 mit SPI2x) hilft sehr wohl. Auch könntest Du mal andere Karten probieren, insbesondere mit kleiner Kapazität. Die verwenden FAT16, was auf dem 8Bit-AVR wesentlich effizienter funktioniert, und zusätzlich ist die FAT nicht so groß. Viele Grüße, Roland
Datum:
Hmmm, ich habe den Code nicht zur Hand, aber eigentlich sollte sd_raw_sync() spätestens in fat_close() automatisch aufgerufen werden.
Datum:
Hallo Werner, Der FAT-Treiber weiß gar nichts vom sd-raw-Modul. Er benutzt nur die Partitionsfunktionen als nächst tieferen Layer. Aber Du hast recht, vielleicht sollte man darüber nachdenken, eine Funktion zum Synchronisieren der Partition bereitzustellen, die dann vom FAT-Treiber an einigen naheliegenden Stellen aufgerufen werden kann. Gruß, Roland
Datum:
Hallo Roland Danke für die Antwort, habe alles mittlerweile gut am laufen. Etwas ist mir jedoch aufgefallen: Wenn ich FAT_DATETIME_SUPPORT einschalte, weil ich auch das Datum und Uhrzeit der Dateierzeugung haben will, überschreibt mir die Funktion fat_create_file(dd, log_file_name, &file_entry) irgendwo den RAM speicher, so dass eine andere meiner Variablen sich verändert. Es muss irgendwo im code liegen der bei FAT_DATETIME_SUPPORT 1 ausgeführt wird. mfg klaus
Datum:
Hallo Klaus! Das halte ich insgesamt für recht unwahrscheinlich, denn der Code für FAT_DATETIME_SUPPORT ist recht trivial. Viel wahrscheinlicher ist, dass ein Stack-Overflow auftritt, wodurch Daten auf dem Heap (also globale Variablen und mit malloc() allokierter Speicher) überschrieben werden. Das kann entweder durch einen Programmierfehler passieren oder schlicht weil der Speicher knapp wird. Wie hast Du denn fat_get_datetime() definiert und implementiert? Gruß, Roland
Datum:
Hallo Roland Ich muss mich bei dir entschuldigen: Deine Software hatte nur indirekt zu tun mit meinem Problem. Das Problem war wie du schon richtig vermutet hast der HEAP! Ich habe einen ATMega32 mit 2k SRAM, und habe nicht gerade sparsam mit dem SRAM programmiert, daher waren meine Variablen schon fast am Ende des SRAM speichers und der HEAP hatte keinen Platz mehr. Aber nun läufts. Danke nochmals für den Hinweis. Und für diejenigen die interessiert wie man am besten feststellen kann wo SRAM Variablen liegen (Adresse) und wo der HEAP Anfängt: Öffnet die MAIN.SYM und sucht dort __bss_end. Bei mir nun : 008005f5 B battery 00800635 B time_ 00800645 B battery_type 00800646 B time_delta_i 0080064a B time2zero 0080064e B __bss_end <------------ Ab der Adresse beginnt der HEAP. Von der maximalen SRAM Speicherstelle abwärts liegt der STACK Wenn sich STACK und HEAP in die Quere kommen hat man ein großes Problem!! Wer das noch genauer lesen will schaut mal hier nach http://www.nongnu.org/avr-libc/user-manual/malloc.html oder auch in Deutsch das Tutorial : http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial
Datum:
Hallo Klaus, Na dann hab ich ja ins Schwarze getroffen. Schön, dass es jetzt funktioniert. Viele Grüße, Roland
Datum:
Hallo, Rolands SD-Reader, um wenige Funktionen erweitert, benutze ich nun schon eine ganze Weile. 24/7 im Dauereinsatz. Ohne Ausfälle. Der älteste Eintrag auf der SD-Karte ist 15.10.2006. Das Teil läuft so gut, das mich nicht mehr traue den nochmal anzufassen. ;) Deswegen habe ich die Hardware neu aufgebaut. Diesmal besser, also mit 3,3V-Regler, anständigem Levelshifter zur Pegelwandlung und beschalteten Pins am Kartenhalter für Karte gesteckt und Schreibschutz aktiviert. Nur mit letzterem habe ich Probleme, alles andere funktioniert sehr gut wie erwartet. Um genau zu sein ist es die Funtion "sd_raw_locked()" welche bei mir genau anders herum funktioniert. Bei meinem Kartenhalter ist es so, das der Kontakt geschlossen ist wenn der Schreibschutz-Schieber auf Stellung "nicht schreibgeschützt" steht. Ist es bei Euch genauso? Vielleicht habe ich ein exotisches Exemplar erwischt welches die Kontakte andersrum schaltet. Um die Verwirrung perfekt zu machen, habe ich mal in der Funktion uint8_t sd_raw_write(offset_t offset, const uint8_t* buffer, uintptr_t length) get_pin_locked() durch sd_raw_locked() ersetzt. Dann geht es ebensowenig. Bin ratlos. Torsten
Datum:
Hallo Torsten, Toll dass Dein Logger so einwandfrei arbeitet. Wenn der Schreibschutz bei Dir andersrum funktioniert, dann ist das doch auch ok. Bei sd_raw_locked() ist übrigens über die Doku festgelegt, in welchen Fällen TRUE bzw. FALSE zurückgegeben wird. get_pin_locked() hingegen liefert direkt den Zustand des entsprechenden Bits im Portregister. Bist Du Dir sicher dass der Schreibschutzschalter wirklich "aus" ist, wenn der Kartenhalter "ein" meldet? Ich komme da immer mit der Markierung auf der Karte selbst durcheinander, die oft nur aus einem Pfeil in Form eines Dreiecks besteht. Da frage ich mich dann oft, ist der Schreibschutz nun in Richtung des Pfeils aktiv? Oder doch eher am dicken Ende? Kannst Du das mit einem PC-Kartenleser nachprüfen? Im Übrigen hatte ich mit dem Schreibschutzschalter am Sockel meines mega-eth auch Probleme, dort funktioniert er gar nicht. Gruß, Roland
Datum:
Hallo,
Ich hatte am Anfang auch Probleme aber nun klappt es bei mir.
sd_raw_config.h:
#define get_pin_available() (PINB & ( 1 << PB4)) // CD von SDC
#define get_pin_locked() (PINB & ( 1 << PB5)) // WP von SDC
...
in sd_raw.c :
uint8_t sd_raw_available()
{
if(get_pin_available())
return 1;
else
return 0;
}
uint8_t sd_raw_locked()
{
if(get_pin_locked())
return 0;
else
return 1;
}
uint8_t sd_raw_write(uint32_t offset, const uint8_t* buffer, uint16_t
length)
{
#if SD_RAW_WRITE_SUPPORT
if(!(get_pin_locked()))
return 0;
...
als Abfrage:
void GetSDCstatus(void){
if (sd_raw_available()){ // SD-Karte eingesteckt
lcd_puts("* SD Card detected *");
if (sd_raw_locked())
lcd_puts("! WP enable !");// Schreibschutz aktiviert
}
else
lcd_puts("! No SDC detected !");
}
Datum:
Ja, ich habe das mehrmals mit dem Kartenleser überprüft. Der Schieber muß in Richtung Kontakte zeigen, dann ist er nicht schreibgeschützt. Nach flüchtigem Betrachten von Esther Ls. Quelltext sieht es scheinbar so aus das der Kontakt dort genauso schaltet. Torsten
Datum:
Hab mich nun auch mit der SD-Karte beschäftigt und den Code von R.R. ausprobiert - bisher leider ohne Erfolg. Was bedeutet "opening partition failed", das bei mir erscheint, sobald ich eine Karte einstecke? Die Schaltkontakte meines Kartensockels schalten beide gegen Masse, als Widerstände hab ich 3K und 1,5K verwendet und die Spannungsversorgung erfolgt über zwei Dioden mit 'nem 100nF Kondensator und 100K gegen Masse. Als Prozessor verwende ich einen ATmega128 mit 14,7456 MHz.
Datum:
Anscheinend kann zwar die Karte angesteuert, das Dateisystem aber nicht geöffnet werden. Hast Du mal einen Schaltplan von Deinem Aufbau? Wie machst Du das Level-Shifting? Welche Karte benutzt Du? Wie wurde sie formatiert? Gruß, Roland
Datum:
Also ich löse das Problem mit Leveln auch mit Widerständen. Man sollte hier aber unbedingt mit dem Oszi die Kurvenverläufe der Leitungen an der SD Karte anschauen. Es sollte ein schöner Rechteck sein. Da durch die Widerstände eine RC Glid entsteht, wird auch das Lade und entladeverhalten eines Kondonsators sichtbar. Ich habe bei meinem Aufbau die Erfahrung gemacht hier den Takt lieber etwas langsamer zu machen. Bei mir lief das eine zeit lang sehr gut, aber aus unersichtlichen Gründen war ab einer gewissen Dauer kein Schreiben auf die Karte möglich. Als ich den Takt auf die nächst mögliche Stufe verkleinert hatte, lief alles einwandfrei, auch auf längere Dauer gesehen.
Datum:
Bin jetzt doch noch einen Schritt weiter gekommen. Nach Durchstöbern der ganzen Config-Files habe ich
#define FAT_FAT32_SUPPORT SD_RAW_SDHC |
in
#define FAT_FAT32_SUPPORT 1 |
geändert. Damit konnte ich dann zwei meiner SD-Karten ansteuern, meine 16MB MMC Karte wollte jedoch immer noch nicht. Außerdem machte eine der beiden SD-Karten Ärger beim Anzeigen des Inhaltsverzeichnisses. Hier geriet die Software in eine Endlosausgabe, da half nur Reset. Hab die Karte dann unter Windows neu formatiert und es ging dann auch mit dieser. Woran es lag, kann ich nicht sagen. Vielleicht zu lange Dateinamen. Was mir noch so auffiel, cat gibt am Ende meist ein paar Bytes zuviel aus.
Datum:
Ja, Unterstützung für Karten >= 4GB ist standardmäßig deaktiviert. Dafür einfach SD_RAW_SDHC in sd_raw_config.h auf 1 setzen, die Änderung an FAT_FAT32_SUPPORT ist dann nicht nötig. Die 16MB-Karte ist vermutlich mit FAT12 formatiert, wofür meine Software keine Unterstützung bietet. Die Implementierung von "cat" ist simpel gehalten, es werden pro Zeile immer acht Bytes ausgegeben, egal ob die Dateilänge durch acht teilbar ist oder nicht. Die zu viel ausgegebenen Bytes stammen dann von der Zeile drüber. Gruß, Roland
Datum:
Meine beiden SD-Karten sind 128MB und 2GB groß, hätten also doch auch ohne Änderung funktionieren müssen. Oder sehe ich das falsch?
Datum:
Also meine 2GB und 1GB SD Karten haben auf Anhieb funktioniert! Also kann es wohl nicht an der Software liegen! Oder sehe ich das falsch?
Datum:
Ich habe heute fünf Karten getestet mit der Version 20081121. Das Ergebnis: Hama 256MB (manuf. 0x04): Wird sofort erkannt. Die Befehle müssen öfters wiederholt werden, damit die Karte arbeitet. Kingston 256MB: Wird sofort erkannt, arbeitet ohne erkennbare Probleme Delkin eFilm 64MB: Wird fast immer sofort erkannt. Wenn sie erkannt wird, läuft sie einwandfrei. Kingston 1GB: Wird nicht erkannt Canon 32MB: Wird nicht erkannt SDHC-Erkennung ist ein. Controller ist der Atmega644P. Gruß Gerd
Datum:
Also meine Kingston 1GB Karte, erst vor wenigen wochen gekauft, lief sofort. Du verwendest doch Widerstandsteiler, oder? Könnte es demnach nicht dem von mir bereits erwähnten Problemen mit zu hohen Clock zusammenhängen? (Machs einfach mal langsamer)
Datum:
Hab mir mittlerweile statt der Widerstandsteiler 'nen 74LVX244 eingebaut, seitdem gehen alle meine Karten auch bei 16MHz Quarztakt, was vorher nicht der Fall war. Nach weiterem Ausprobieren sehe ich, dass das Programm hängt, wenn ich eine Datei mit dem "cat" Befehl ausgebe und anschließend eine neue Karte einstecke. Diese wird mit dem init-Befehl nicht mehr richtig angemeldet, weshalb dann nur Reset hilft. Da fehlt also noch irgendwas im Quellcode. Leider bin ich in der Materie nicht soweit drin um sagen zu können, was da genau schief geht.
Datum:
Angehängte Dateien:Also ich hab die SD_RAW.C Datei etwas verändert. Diese Änderung bewirkt eine art Timeout, welche das Aufhängen der Software verhindert. Die Stellen im Code sind mit JKLM gekennzeichet. Zustande kommt das Aufhängen, wenn die Karte keine oder falsche Rückgabewerte liefert. Sollte wenn alles funktioniert ja nie auftreten, aber was funkt schon immer. Ich hoffe das hilft. gruß meini
Datum:
Hallo meini,
>Du verwendest doch Widerstandsteiler, oder?
Richtig!
Ich bin gerade verschieden Sachen am Durchprobieren und mir fällt auf,
das Ulrich Radig in seiner SW auch mit niedrigsten SPI-Takt
initialisiert und dann auf maximalen SPI-Takt hochschaltet. Mit dieser
SW laufen alle Karten die ich habe. Zur Zeit versuche ich mit
Debugausgaben herauszufinden, was schief läuft.
Atmega644p
14,7456MHz
Widerstandsteiler nach Radig.
Gruß Gerd
Datum:
Hallo Gerd Also das Initialisieren mit niedrigstem Takt macht auch Rolands software. Anschließend wird dann auf den Arbeitstakt hochgeschaltet. Ja ich arbeite mit widerstandsteilern. Bis auf die genannten Probleme funktioniert es immer auf anhieb. Das Aufhängen kommt meist daher, dass die software auf ein Rückgabebyte wartet. Kommt es nicht, oder kommt ein falsches Byte zurück bleibt die Software dort in der schleife stecken. Es wrid zuerst ein Kommandobyte an die Karte geschrieben, und danach auf die Rückmeldung gewaretet. Bei mir ist es meist schiefgelaufen, wenn ich die Karte aus dem Slot genommen habe. glus klaus
Datum:
Hallo Gerd, Auch die 3,3V Versorgung der Karte könnte die Ursache für so ein Verhalten sein. Wenn noch nicht geschehen, dann unbedingt die Dioden gegen einen geeigneten Festspannungsregler tauschen. Torsten
Datum:
Die 3,3V Spannungsversorgung ist durch einen LM317 gegeben. Wie gesagt, kriege ich nicht alle SD-Karten mit Rolands Programm initialisiert. Da ich gerade noch ein anderes Problem lösen muss, das damit nichts zu tun hat, wird meine Rückmeldung zu diesem Thema erst in den nächsten Tagen kommen. Wenn ich Ulrichs Programm verwende, werden alle Karten erkannt. Da sieht die Init so aus:
//############################################################################ //Routine zur Initialisierung der MMC/SD-Karte (SPI-MODE) unsigned char mmc_init () //############################################################################ { unsigned int Timeout = 0; //Konfiguration des Ports an der die MMC/SD-Karte angeschlossen wurde MMC_Direction_REG &=~(1<<SPI_DI); //Setzen von Pin MMC_DI auf Input MMC_Direction_REG |= (1<<SPI_Clock); //Setzen von Pin MMC_Clock auf Output MMC_Direction_REG |= (1<<SPI_DO); //Setzen von Pin MMC_DO auf Output MMC_Direction_REG |= (1<<MMC_Chip_Select); //Setzen von Pin MMC_Chip_Select auf Output MMC_Direction_REG |= (1<<SPI_SS); MMC_Write |= (1<<MMC_Chip_Select); //Setzt den Pin MMC_Chip_Select auf High Pegel for(unsigned char a=0;a<200;a++){ nop(); }; //Wartet eine kurze Zeit #if SPI_Mode //Aktiviren des SPI - Bus, Clock = Idel LOW //SPI Clock teilen durch 128 SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1); //Enable SPI, SPI in Master Mode SPSR = (0<<SPI2X); #endif //Initialisiere MMC/SD-Karte in den SPI-Mode for (unsigned char b = 0;b<0x0f;b++) //Sendet min 74+ Clocks an die MMC/SD-Karte { mmc_write_byte(0xff); } //Sendet Commando CMD0 an MMC/SD-Karte unsigned char CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95}; while(mmc_write_command (CMD) !=1) { if (Timeout++ > 200) { MMC_Disable(); return(1); //Abbruch bei Commando1 (Return Code1) } } //Sendet Commando CMD1 an MMC/SD-Karte Timeout = 0; CMD[0] = 0x41;//Commando 1 CMD[5] = 0xFF; while( mmc_write_command (CMD) !=0) { if (Timeout++ > 400) { MMC_Disable(); return(2); //Abbruch bei Commando2 (Return Code2) } } #if SPI_Mode //SPI Bus auf max Geschwindigkeit SPCR &= ~((1<<SPR0) | (1<<SPR1)); SPSR = SPSR|(1<<SPI2X); #endif //set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv) MMC_Disable(); return(0); } |
Ich melde mich wieder, wenn ich das andere Problem gelöst habe. Gruß Gerd
Datum:
Hey, mal ne ganz andere Frage. Hat schon mal jemand probiert das ganze in Assembler zu programmieren?
Datum:
Warum sollten wir diesen Thread in Assembler umschreiben? Such mal im Forum danach. Da hab ich sowas schon gesehen. So eine komplexe Aufgabe wie die SD-Karte ist doch keine geeignete Aufgabe für Assembler-only. Du kannst dir natürlich das compilierte Listing File anschauen und daraus deinen Code stricken. Hallo meini, es ist mit deinem Time-Out-Schleifen zwar etwas besser geworden (besten Dank dafür) aber noch nicht beseitigt. Spiel ich etwas rum, schaffe ich es weiterhin, die Software schnell zu verwirren. Da werd ich mir die U.R. SW auch noch mal ansehen. Letztlich such ich eine Software, die dauerhaft ohne manuellen Eingriff funktioniert.
Datum:
Hallo Habe mir einen Temperatur Logger auf Basis eines ATmega128 Boards und einem SD-Kartenleser gebaut. Funktioniert soweit wunderbar. Danke an alle Beteiligten und vorallem an Roland Riegel für seine Software. Zwei Sachen sind mir aber noch nicht ganz klar: 1. Wie hänge ich Daten an ein bestehendes File an. Stimmt das folgendes Vorgehen: - sd_raw_init() - partition_open() - fat_open() - fat_get_dir_entry_of_path() - fat_open_dir() - open_file_in_dir(fs, dd, "mmc.txt"); - fat_seek_file(fd, &write_offset, FAT_SEEK_END)) // write_offset = 0 - fat_write_file(fd, (uint8_t*) "Zeile2\n", 7) - sd_raw_sync(); - fat_close_file(fd); - fat_close(fs); - partition_close(partition); Ganz falsch kann es nicht sein, mein File hat die Zeile drin und ist auf Windows und Linux noch lesbar ;-) Oder anders gefragt, ist mir nicht klar, ob ich nun das File zuerst mit resize vergrössern muss oder direkt reinschreiben kann ? 2. Sicheres Vorgehen gegen Datenverlust Da mein Logger alle 60s einen Datensatz von ca. 25 Bytes in das File schreiben wird, kann ich doch jedesmal das File öffnen, die Daten reinschreiben und alles wieder schliessen, so dass das Filesystem ok ist. Oder spricht etwas dagegen ? Ich weiss, ich könnte das File am Anfang öffnen, im Minutentakt reinschreiben und am Schluss, z.B. nach einem Button-klick, schliessen und gut. Aber was passiert dazwischen, wenn der Strom ausfällt oder so ? Daten wohl weg, und Filesystem korrupt. Besten Dank und Gruss Daniel
Datum:
Hallo Daniel, 1. Das stimmt so. fat_resize_file() bietet sich bei vielen oder großen Anhängeoperationen an, um die Datei im Vorhinein zu vergrößern, so dass der Verzeichniseintrag (der die Größe enthält) nicht bei jedem fat_write_file() geschrieben werden muss. 2. Wie Du es machst ist egal. Wichtig ist nur der Aufruf von sd_raw_sync(). Das ganze Drumherum der Handles ändert nichts an der Konsistenz des Dateisystems, sondern puffert nur einige wichtige Informationen über die Partition, das Dateisystem, die Datei usw.. Wenn Du nach fat_write_file() sd_raw_sync() aufrufst, ist alles in einem konsistenten Zustand. Wenn Du den Kartentausch nur in ausgeschaltetem Zustand vorsiehst, brauchst Du nie fat_close_file(), fat_close() etc. aufrufen. Viele Grüße, Roland
Datum:
Hi, ich habe anscheinend Probleme beim Aufbau der Schaltung, und weiß langsam nichtmehr wo der Fehler noch sein könnte. Sobald ich get_pin_available() und get_pin_locked() auf null setze produziert avrdude nach dem flashen beim fuse-check nen Fehler, aber ist ja irgendwie auch logisch und dürfte denk ich nicht viel machen. Allerdings herrscht auf dem UART dann auch absolute Stille. Beim Spannungsteiler hab ich 2k2 und 4k7 Ohm, aber Hauptsache das Verhältniss ist ungefähr das gleiche, oder? Die Versorungsspannung lege ich zwischen GND und der Karte mit einem Netzteil an, der AVR wird über den USB ISP versorgt, der ja Erdfrei sein müsste. Die Karte funktioniert am PC und der mC ist ein ATmega32. So, mehr fällt mir eigentlich nichtmehr ein.
Datum:
Hallo Alexander, > Sobald ich > get_pin_available() und get_pin_locked() auf null setze produziert > avrdude nach dem flashen beim fuse-check nen Fehler, aber ist ja > irgendwie auch logisch und dürfte denk ich nicht viel machen. Was ist daran logisch?? Was hat ein Ändern von Konstanten im Programm mit den Fuses und dem Verhalten von avrdude zu tun? Setze #define configure_pin_available() /* empty */ #define configure_pin_locked() /* empty */ #define get_pin_available() 0 #define get_pin_locked 1 > Beim Spannungsteiler > hab ich 2k2 und 4k7 Ohm, aber Hauptsache das Verhältniss ist ungefähr > das gleiche, oder? Im Prinzip schon. Denk aber bitte dran dass je größer die Widerstandswerte sind desto flacher werden die Signalflanken. > Die Versorungsspannung lege ich zwischen GND und der > Karte mit einem Netzteil an, der AVR wird über den USB ISP versorgt, der > ja Erdfrei sein müsste. Die Karte funktioniert am PC und der mC ist ein > ATmega32. So, mehr fällt mir eigentlich nichtmehr ein. Kannst Du mal nen Schaltplan skizzieren? Das mit der Erde ist mir nicht ganz klar. Versorge mal alles aus einer einzigen Spannungsquelle und spendier der Karte einen richtigen Regler. Gruß, Roland
Datum:
danke für die schnelle Antwort. Ich hab das ganze jetzt auf 3.3V laufen, da der Atmega32 damit auch noch läuft. Jetzt kommt er immerhin zu dem Schluss dass "MMC/SD initialization failed". Ich hab herausgefunden, dass response = sd_raw_send_command(CMD_GO_IDLE_STATE, 0); nicht die erwartete Antwort sondern 0xff liefert.
Datum:
Alles auf 3,3V laufen zu lassen ist natürlich auch ok. Ein paar Ideen: - Blockkondensatoren (50uF und 100nF) direkt an der Karte - möglichst kurze SPI-Leitungen - ISP-Programmer vor uC-Start abziehen (zu lange Leitungen) - Pinbelegung an der Karte überprüfen - MISO (also DO der Karte) mit Pullup ca. 50k auf 3,3V - Signale und Vcc mit Oszilloskop anschauen Die Karte kann beim Initialisieren und v.a. auch bei Zugriffen recht viel Strom ziehen, dass sollte die Spannungsquelle liefern können. Was hast Du sonst an der Schaltung hängen? Hast Du einen festen Aufbau auf Platine oder eine Freiluftverdrahtung? Welche Änderungen hast Du an der Software im Vergleich zum Original vorgenommen? Viele Grüße, Roland
Datum:
Hi. Ich habe ein Problem mit dem Debuggen, wenn ich die SD-Bibliothek eingebunden habe. Solange ich nur die Karte initialisiere ist alles I.O.. Sobald ich das öffenen der Partition mit in meinen Code aufnehme, bekomme ich Abstürze von AVR-Studio. Ich arbeite mit - Rolands Bibliothek Version 2008-11-21 - AVR-Studio 4.15.623 - WINAVR 20081205 - JTAGICEmkII (Firmware-Update von AVR-Studio 4.15.623) - ATmega2560 oder ATmega644 Sobald ich diesen Codeabschnitt mit reinehme, stürzt AVR-Studio mit einem MFC-Fehler ab sobald ich irgendwo in partition_open() einen Breakpoint setze:
if(!partition) { /* If the partition did not open, assume the storage device * is a "superfloppy", i.e. has no MBR. */ partition = partition_open(sd_raw_read, sd_raw_read_interval, sd_raw_write, sd_raw_write_interval, -1 ); if(!partition) { #if DEBUG uart_puts_p(PSTR("opening partition failed\n")); #endif continue; } } |
Hat irgendjemand etwas ähnliches beobachtet und kann mir vieleicht einen Tip geben? Ich kann es mir nicht erklären, was da genau passiert.
Datum:
Hm, da habe ich keine Ahnung, ich arbeite nicht mit dem AVR-Studio. Vielleicht kommt es mit den Funktionspointern und den zugehörigen typedefs durcheinander? Schon mal eine andere Studio-Version ausprobiert? Gruß, Roland
Datum:
Ich habe schon die neue 4.16-beta ausprobiert, aber da ist es das gleiche. Ältere Versionen muß ich nochmal raussuchen. Ich schau mir mal die Funktionspointer an. Danke
Datum:
Abend, ich habe Probleme beim öffnen/finden einer Datei. Controller ist ein ATmega32. Kann mir mal bitte jemand auf die Sprünge helfen, was ich falsch mache bzw. was ich vergessen habe? Hier steigt mein Programm aus: if(!fd) { vLCD_Control(ZEILE_2, "error opening "); } Und hier der ganze Code:
global void vSD_Init(void) { uint8 buffer[24]; if(sd_raw_init() == TRUE) { vLCD_Control(ZEILE_1, "SD-Card found"); // open first partition struct partition_struct* partition = partition_open( sd_raw_read, sd_raw_read_interval, /*sd_raw_write*/ 0, /*sd_raw_write_interval*/ 0, 0 ); if(partition == FALSE) { /* If the partition did not open, assume the storage device * is a "superfloppy", i.e. has no MBR. */ partition = partition_open( sd_raw_read, sd_raw_read_interval, /*sd_raw_write*/ 0, /*sd_raw_write_interval*/ 0, -1 ); if(partition == FALSE) { vLCD_Control(ZEILE_1, "opening partition failed"); } } // open file system struct fat_fs_struct* fs = fat_open(partition); if(fs == FALSE) { vLCD_Control(ZEILE_1, "opening filesystem failed"); } else { // open root directory struct fat_dir_entry_struct directory; fat_get_dir_entry_of_path(fs, "/", &directory); struct fat_dir_struct* dd = fat_open_dir(fs, &directory); if(dd == FALSE) { vLCD_Control(ZEILE_2, "opening root directory failed"); } else { // print some card information as a boot message print_disk_info(fs); // search file in current directory and open it struct fat_file_struct* fd = open_file_in_dir(fs, dd, "test.txt"); if(!fd) { vLCD_Control(ZEILE_2, "error opening "); } else { fat_read_file(fd, buffer, sizeof(buffer)); } } } } else { // Init of SD-Card failed vLCD_Control(ZEILE_1, "SD-Card failed"); } } |
Datum:
Es könnte ein Problem mit der Schreibweise sein. Wenn diese Datei unter Windows erstellt wurde, probier mal:
struct fat_file_struct* fd = open_file_in_dir(fs, dd, "test.TXT"); |
Torsten
Datum:
Die Datei wurde unter Windows erstellt, test.TXT hatte aber auch nichts gebracht. Ist denn die Art und Weise, wie ich das FAT16 System initialisiere und die Datei suche/öffne so richtig?
Datum:
Hallo Marcel, Ich finde Deinen Code mit den ganzen verschachtelten ifs etwas unübersichtlich. Mach es lieber so:
if(!partition) { /* lcd error message */ return; } /* ... */ if(!fs) { /* output lcd error message */ return; } /* etc. */ |
Und vergleiche die zurückgegebenen Handles bitte nicht mit FALSE, das sieht so aus als würde die Funktion einen Wahrheitswert zurückgeben, was sie aber nicht tut. Entweder "== 0" bzw. "!= 0" oder den Handle direkt als Wahrheitswert verwenden (wie im Ausschnitt oben). Wenn ich mich durch die missglückte Formatierung des Codeausschnitts nicht in die Irre habe führen lassen, versuchst Du, das Dateisystem auch dann zu öffnen, wenn die Partition gar nicht geöffnet werden konnte. Ansonsten hat Torsten Recht, die aktuelle sdreader-Version behandelt die Groß-/Kleinschreibung von Dateien nicht immer korrekt, die unter Windows NT/2000/XP/Vista angelegt wurden. Vielleicht also statt dem Öffnen der Datei erst mal versuchen, alle Dateien auf der Karte aufzulisten. Wenn die Groß-/Kleinschreibung für Dich ein Problem sein sollte, findest Du in dem folgenden Beitrag den Patch, der das Problem behebt: Beitrag "Re: MMC/SD-Karte mit FAT16 an AVR" Gruß, Roland
Datum:
Hallo Roland, erstmal klasse, daß du uns dieses Projekt zur Verfügung stellst...habe dennoch ein kleines Problem mit sd_raw.c:
/* wait for card to get ready */
for(uint16_t i = 0; ; ++i)
{
if(sd_raw_card_type & ((1 << SD_RAW_SPEC_1) | (1 << SD_RAW_SPEC_2)))
{
uint32_t arg = 0;
#if SD_RAW_SDHC
if(sd_raw_card_type & (1 << SD_RAW_SPEC_2))
arg = 0x40000000;
#endif
sd_raw_send_command(CMD_APP, 0);
response = sd_raw_send_command(CMD_SD_SEND_OP_COND, arg);
}
else
{
response = sd_raw_send_command(CMD_SEND_OP_COND, 0);
}
if((response & (1 << R1_IDLE_STATE)) == 0)
{
break;
}
if(i == 0x7fff)
{
unselect_card();
return 0;
}
}
|
Ich bekomme bei der ersten if-Abfrage stetig eine response von 255, d.h. die for-schleife wird nie verlassen, da die vorletzte if-Abfrage nie wahr wird. Kann die Erklärung dafür sein, das meine 16MB Panasonic Karte nicht richtig funktioniert? In Windos kann ich sie ganz normal lesen und beschreiben. Habe einen ATMega168 mit deiner exakten Verschaltung. Hoffe, du hast einen Tip für mich. Gruß Stefan
Datum:
Hallo Stefan, Hättest Du für den Anfang nicht vielleicht noch eine etwas größere (d.h. neuere) SD-Karte zum Testen? Ich weiß nicht, wie genau sich diese alten MMC-Karten an die Spezifikation halten. Auch habe ich keine hier, mit der ich selbst testen könnte. Zudem wirst Du Probleme mit dem Zugriff auf die Dateien bekommen, denn die 16MB werden normalerweise noch mit FAT12 verwaltet, wofür der sd-reader keine Unterstützung bietet. Gruß, Roland
Datum:
Abend, Problem gelöst --> vielen Dank Es muss
struct fat_file_struct* fd = open_file_in_dir(fs, dd, "TEST.TXT"); |
heißen. Der Tipp mit dem Auflisten der Dateien auf der Karte hat voll ins Schwarze getroffen. Auch wenn trivial, da wäre ich nie alleine drauf gekommen ;) SChönes Wochenende
Datum:
Hallo, kann mir einer die Eagle-Datei (Schaltplan) in eine PDF/Bild umwandeln? Ich überlege im moment gerade ein kleines Sprachausgabe-Modul zu basteln, als externen, leicht verwaltbaren Speicher würde sich eine SD-Karte da ja anbieten, einfach neue "WAV's" aufspielen und schon klappt es mit der ausgabe ;-)
Datum:
Schau Dir mal die Exportieren-Funktion von Eagle an. (Datei->Exportieren->Image) Ansonsten ausdrucken und z.B. freepdfxp benutzen.
Datum:
Hallo Roland, Du hattest wie immer den richtigen Riecher bzgl. meiner Speicherkarte, die nur 16MB groß ist. Habe mir eine 2GB Karte gekauft, jetzt scheint es zu funktionieren!! Meine 16MB Karte ist übrigens keine MMC, sondern auch eine SD, aber egal... Vielen Dank nochmal für die Mühe. Stefan
Datum:
ähm ja, aber ich haben gar kein eagle ... das ist das problem ....
Datum:
Dann lade Dir sie Dir doch bei Cadsoft runter. Nach der Installation als freeware lizensieren. Damit kann man zwar nur Platinen mit einem Schaltplanblatt und nur 100x80mm zaubern, aber öffnen kann man auch größere Projekte.
Datum:
Michael W. wrote: > kann mir einer die Eagle-Datei (Schaltplan) in eine PDF/Bild umwandeln? Wenn Du den Thread mal nach "pdf" oder "png" durchsucht hättest, wärst Du auf diesen Beitrag gestoßen: Beitrag "Re: MMC/SD-Karte mit FAT16 an AVR" Gruß, Roland
Datum:
Hallo, ich wollte diese Schaltung nachbauen, aber habe noch 2 Fragen: Sehe ich das richtig, dass J1 der Slot für die SD/MMC Karte ist? Worum handelt es sich bei JP3 und JP4? Danke Alex
Datum:
Noch etwas vergessen: Also J1 muss ja der SD Slot sein, was bedeuten Pins 10-12? Eine SD Karte hat doch nur 9 Pins? Welchen Wert sollte man für C5 nehmen? Hätte jemand die genaue Bezeichnung von Q1 für mich? Vielen Dank!
Datum:
Hallo Alex, > Sehe ich das richtig, dass J1 der Slot für die SD/MMC Karte ist? Ja klar. > Worum handelt es sich bei JP3 und JP4? Das ist die UART. > Also J1 muss ja der SD Slot sein, was bedeuten Pins 10-12? Anschlüsse für Card-Detect- bzw. Write-Lock-Schalter. Nicht zwingend notwendig. > Welchen Wert sollte man für C5 nehmen? Je nach Netzteil, 50µF bis 200µF sind allemal ok. > Hätte jemand die genaue Bezeichnung von Q1 für mich? Jeder x-beliebige 16MHz-Grundton-Quarz. Kannst auch ne andere Frequenz nehmen, musst dann aber die Software anpassen. Reichelt: http://www.reichelt.de/?ARTICLE=32852 Gruß, Roland
Datum:
Angehängte Dateien:Hallo zusammen! Ein neues sd-reader-Release ist fertig (siehe Anhang). Hauptsächlich enthält es Bugfixes und einige Schönheitskorrekturen. Im einzelnen: - Benutze Info über Groß-/Kleinschreibung für Dateinamen und -erweiterungen, wie sie von Windows NT und später geschrieben werden. - Standard-Pinkonfiguration für den ATmega328. - MMC/SD/SDHC-Unterscheidung korrigiert. - Blockpufferung korrigiert. - Größenberechnung für FAT16 bei Verwendung einer FAT32-Konfiguration korrigiert. - Kompilierungsfehler bei Nur-Lese-Konfiguration beseitigt. - Korrekte Logik für den Schreibschutz. - Vereinfachte Einbindung in C++-Anwendungen. Neu auf der Projekt-Homepage gibt es auch einen neuen, verbesserten Schaltplan sowie eine FAQ-Seite http://www.roland-riegel.de/sd-reader/faq/ und eine Benchmark-Seite http://www.roland-riegel.de/sd-reader/benchmarks/ Viel Spaß damit, Roland
Datum:
Ich habe ein kleines Problem, ich hab ein Board mit einem Atmega32, die SD-Karte wird erkannt und ich kann Daten aus einem File lesen. Schreiben hat auch funktioniert, ich habe aber etwas am Code rumgebastelt und jetzt funktioniert es nicht mehr. Es kommt jedoch keine Fehlermeldung. Hier mal ein Teil des Codes, der obere Teil, der fehlt, ist identisch mit dem original Code. Vieleicht sieht ja jemand mein Fehler, ich bin schon am verzweifeln.
while(fat_read_dir(dd, &directory)) { if(strcmp(directory.long_name, "test.txt") == 0) { strcpy(test,directory.long_name); uart_puts(test); break; } } struct fat_file_struct * file = fat_open_file(fs,&directory); if(!file) { uart_puts_p(PSTR("file error\n")); } else { uart_puts_p(PSTR("file ok\n")); } char write[] = "test"; int data_len = 1+strlen(write); if(fat_write_file(file, (uint8_t*) write, data_len) != data_len) { uart_puts_p(PSTR("error writing to file\n")); break; } else { uart_puts("file beschrieben \n"); } fat_close_file (file); return 0; |
Datum:
Hallo Jan, Jan wrote: > Ich habe ein kleines Problem, ich hab ein Board mit einem Atmega32, die > SD-Karte wird erkannt und ich kann Daten aus einem File lesen. Ok. > Schreiben > hat auch funktioniert, ich habe aber etwas am Code rumgebastelt und > jetzt funktioniert es nicht mehr. Es kommt jedoch keine Fehlermeldung. Was genau hast Du wo herumgebastelt? Was funktioniert nicht mehr? Was soll funktionieren? Was passiert stattdessen (oder eben nicht)?
> while(fat_read_dir(dd, &directory)) > { > if(strcmp(directory.long_name, "test.txt") == 0) > { > > strcpy(test,directory.long_name); > > uart_puts(test); > break; > } > > } |
Was passiert (oder soll passieren), wenn die Datei nicht gefunden wird? In Deinem Code wird einfach weitergemacht, was dann natürlich schiefgeht. (Noch ein hypothetischer Fall: Wass passiert, wenn "test.txt" ein Ordner ist?) Und: Warum kopierst Du den Dateinamen in einen mysteriösen Puffer (dessen Größe hoffentlich ausreichend ist), wenn Du directory.long_name auch direkt ausgeben kannst?
> struct fat_file_struct * file = fat_open_file(fs,&directory); > if(!file) > { > uart_puts_p(PSTR("file error\n")); > } > else > { > uart_puts_p(PSTR("file ok\n")); > } |
Was passiert nach einem Fehler beim Öffnen der Datei? Du machst schon wieder einfach weiter!
> char write[] = "test"; > > int data_len = 1+strlen(write); |
Warum "+1"? Willst Du das Null-Byte am Ende des Strings wirklich in der Datei haben?
> if(fat_write_file(file, (uint8_t*) write, data_len) != data_len) > { > uart_puts_p(PSTR("error writing to file\n")); > break; > } |
Warum "break"? Auf welche Schleife bezieht sich das? Also, knapp gesagt: Rechne immer mit Fehlern und reagiere darauf, und zwar nicht nur mit einer Fehlermeldung über UART! Gruß, Roland
Datum:
Hallo Roland, ich habe Deine Lib mit verschiedenen Karten ausprobiert, allerdings bleibe ich immer beim Öffnen des Filesystems hängen. Windows erkennt die Karten (16MB, 32MB,64MB,2GB) ganz normal. Habe einige Karten in einer Digitalkamera neu formatiert. Ich verwende die ersten Teile aus Deiner main.c, daher sollte es eigentlich funktionieren (?). Das Init klappt auch soweit, da bekomme ich keinen Fehler. Partition scheint auch ok zu sein. Hardwareaufbau ist ein AtMega644 16Mhz, SD-Karte mit 3,3V Regler und Widerständen und Abblockkondensatoren. Viele Grüße, Thorsten
Datum:
Hallo Thorsten, Mit welchen Dateisystemen sind die Karten formatiert? Zumindest die 16MB-Karte müsste mit FAT12 formatiert sein, welches von meinem Code nicht unterstützt wird. Benutze zur Formatierung bitte Windows oder noch besser unter Linux mkdosfs. Wo genau scheitert fat_open()/fat_read_header()? Füge bitte Haltepunkte oder UART-Ausgaben an mehreren Stellen ein und verfolge nach, wo der Code aussteigt. Vielleicht magst Du mir per Mail auch mal Deinen Code schicken. Gruß, Roland
Datum:
Windos sagt FAT, Linux habe ich nicht installiert. Werde die UART-Ausgaben mal verfeinern. Der Code ist die aktuelle Lib von Deiner Homepage.
Datum:
Habe jetzt mal Winhex installiert und siehe da, es ist FAT12. Schade, da muss ich wohl noch mal schauen, wie ich das Format ändern kann.
Datum:
Hallo, Eine Anmerkung und eine Frage:
void sd_raw_send_byte(uint8_t b) { SPDR = b; /* wait for byte to be shifted out */ while(!(SPSR & (1 << SPIF))); SPSR &= ~(1 << SPIF); } |
Die Zeile SPSR &= ~(1<<SPIF); ist imho a) Quatsch und b) unnötig. a) Löscht man ein Interrupt Flag durch Schreiben einer 1 an der Stelle und b) SPIF wird automatisch gelöscht, wenn SPSR mit gesetztem SPIF gelesen wurde. Ich habe aber Probleme die ganze Library in ein Projekt einzubinden, wo an der SPI Schnittstelle auch noch ein ENC28J60 hängt. Nach dem sd_raw_init funktioniert erst mal nichts mehr. Überprüft habe ich: -CPOL und CPHA haben schon mal die gleichen Einstellung bei SD Karte und ENC28J60 (beides MODE 0). -Den SS Pin für die Karte habe ich in den Definitionen umgelegt auf einen anderen Port. Eventuell hast du noch eine Idee welche Aktionen aus deiner Library mit einer anderen SPI Library kollidieren könnten. Danke schon mal!
Datum:
So, hier der Code. Die Partition Routine gibt keinen Fehler zurück, der Code bleibt in der ersten Anweisung in fat_open hängen, da partition auf einmal null zu sein scheint.
/* setup sd card slot */ if(!sd_raw_init()) { uart_puts_p(PSTR("MMC/SD initialization failed\n")); _delay_ms(20); return 0; } /* open first partition */ struct partition_struct* partition = partition_open(sd_raw_read, sd_raw_read_interval, #if SD_RAW_WRITE_SUPPORT sd_raw_write, sd_raw_write_interval, #else 0, 0, #endif 0 ); if(!partition) { /* If the partition did not open, assume the storage device * is a "superfloppy", i.e. has no MBR. */ partition = partition_open(sd_raw_read, sd_raw_read_interval, #if SD_RAW_WRITE_SUPPORT sd_raw_write, sd_raw_write_interval, #else 0, 0, #endif -1 ); if(!partition) { uart_puts("opening partition failed\n"); } } /* open file system */ struct fat_fs_struct* fs = fat_open(partition); if(!fs) { uart_puts("opening filesystem failed\n"); } |
Und hier der Code aus fat.c:
struct fat_fs_struct* fat_open(struct partition_struct* partition) { uart_puts("fat_open\n"); if(!partition || #if FAT_WRITE_SUPPORT !partition->device_write || !partition->device_write_interval #else 0 #endif ) return 0; uart_puts("1\n"); |
Die 1 sehe ich jedenfalls nicht mehr in der Debug-Ausgabe.
Datum:
Simon K. wrote: > Ich habe aber Probleme die ganze Library in ein Projekt einzubinden, wo > an der SPI Schnittstelle auch noch ein ENC28J60 hängt. Nach dem > sd_raw_init funktioniert erst mal nichts mehr. Also: sd_raw_init() läuft bis zu dieser Stelle:
#if !SD_RAW_SAVE_RAM /* the first block is likely to be accessed first, so precache it here */ raw_block_address = (offset_t) -1; #if SD_RAW_WRITE_BUFFERING raw_block_written = 1; #endif if(!sd_raw_read(0, raw_block, sizeof(raw_block))) return 0; #endif |
Und bleibt bei sd_raw_read(...) hängen(!). Hab schon mal hier in dem Thread ein wenig gesucht, scheint aber ein unbekanntes Problem zu sein? Ich werde die Sache noch mal weiter verfolgen. Innerhalb von sd_raw_read bleibt es hier hängen:
/* wait for data block (start byte 0xfe) */
while(sd_raw_rec_byte() != 0xfe);
|
Und zwar, weil die Karte 0xFF zurückgibt. Na sowas. Es werden keine Pegelwandler verwendet, das ganze System läuft auf 3,3V. Zum Einsatz kommt eine µSD Karte von extrememory.
Datum:
Hallo Simon, Simon K. wrote: > Eine Anmerkung und eine Frage: >
> void sd_raw_send_byte(uint8_t b) > { > SPDR = b; > /* wait for byte to be shifted out */ > while(!(SPSR & (1 << SPIF))); > SPSR &= ~(1 << SPIF); > } > |
> > Die Zeile SPSR &= ~(1<<SPIF); ist imho a) Quatsch und b) unnötig. a) > Löscht man ein Interrupt Flag durch Schreiben einer 1 an der Stelle und > b) SPIF wird automatisch gelöscht, wenn SPSR mit gesetztem SPIF gelesen > wurde. Danke für die Anregung. Ich werd mir das mal ansehen. Eventuell ist es bei gewissen Reihenfolgen von sd_raw_send_byte()/sd_raw_rec_byte() notwendig, so genau weiß ich das nicht mehr. > Ich habe aber Probleme die ganze Library in ein Projekt einzubinden, wo > an der SPI Schnittstelle auch noch ein ENC28J60 hängt. [...] > > Eventuell hast du noch eine Idee welche Aktionen aus deiner Library mit > einer anderen SPI Library kollidieren könnten. Schau Dir mal mega-eth unter http://www.roland-riegel.de/mega-eth/ an, dort habe ich genau dieses Problem durch ein kleines zusätzliches SPI-Interface gelöst. > Innerhalb von sd_raw_read bleibt es hier hängen:
> /* wait for data block (start byte 0xfe) */ > while(sd_raw_rec_byte() != 0xfe); |
Vermutlich stört da der ENC28J60 irgendwie. Wie schon gesagt, schau Dir mal meine obige Lösung an. Gruß, Roland
Datum:
niketchana wrote: > Hallo, > jetzt geht´s. Das war ein Problem der Formatierung.Anscheinend > formatiert Window mit FAT12.Ich habe die Karte mit dem "SD Formatter > 2.0.0.3 von Panasonic" formatiert und schon geht alles. > niketchana Hi Roland, Danke für den Tipp mit dem mega-eth. Das Problem ist doch schon mal aufgetreten in diesem Thread und somit ließ sich eine Lösung finden. Jetzt bleibt er wenigstens nicht hängen.
Datum:
Servus Thorsten, Das hier...
> /* open first partition */ > struct partition_struct* partition = partition_open( > sd_raw_read, > sd_raw_read_interval, > #if SD_RAW_WRITE_SUPPORT > sd_raw_write, > sd_raw_write_interval, > #else > 0, > 0, > #endif > 0 > ); > > /* ... */ > > /* open file system */ > struct fat_fs_struct* fs = fat_open(partition); > if(!fs) > { > uart_puts("opening filesystem failed\n"); > } |
... in Verbindung damit...
> struct fat_fs_struct* fat_open(struct partition_struct* partition) > { > uart_puts("fat_open\n"); > > if(!partition || > #if FAT_WRITE_SUPPORT > !partition->device_write || > !partition->device_write_interval > #else > 0 > #endif > ) > return 0; > uart_puts("1\n"); |
... sagt mir, dass Du zwar FAT_WRITE_SUPPORT auf 1 gesetzt hast, SD_RAW_WRITE_SUPPORT aber auf 0 steht. Viele Grüße, Roland
Datum:
Hallo Roland, nachdem ich FAT_WRITE_SUPPORT auch auf 1 gesetzt habe, bekomme ich Zugriff auf die Karte :-) (Obwohl ich doch nur lesen wollte) Vielen Dank für die Hilfe (verneig) ! Thorsten
Datum:
Hallo Thorsten, Schön, dass es jetzt wieder funktioniert. Wenn Du insgesamt nur Leseunterstützung brauchst, kannst Du natürlich beides (FAT_WRITE_SUPPORT und SD_RAW_WRITE_SUPPORT) auf 0 setzen. fat_open() überprüft die Funktionsargumente, und wenn FAT-Schreibunterstützung aktiviert wurde, jedoch keine Funktionszeiger zum Schreiben auf den Datenträger übergeben werden, endet fat_open() mit einem Fehler. Gruß, Roland
Datum:
Ich hatte den Write-Support auf 1, aber vergessen in der fat.h auch den write-support zu setzen. Vielleicht kannst Du die Doku etwas ändern, damit man auf diese Abhängigkeit etwas hingewiesen wird.
Datum:
@Simon > So, bei mir läuft jetzt auch alles wie gewünscht. :-) Sehr schön :) @Thorsten > Vielleicht kannst Du die Doku etwas ändern, damit man auf diese > Abhängigkeit etwas hingewiesen wird. Ich werde mir was überlegen. Gruß, Roland
Datum:
Hallo Roland, vielen Dank für deine Hinweise, > Was genau hast Du wo herumgebastelt? Was funktioniert nicht mehr? Was > soll funktionieren? Was passiert stattdessen (oder eben nicht)? Hier ist das Problem: Ich weiß leider nicht mehr was ich verändert habe. Ich konnte vorm "rumbasteln" eine Datei öffnen und etwas in die Datei schreiben. Jetzt kann ich zwar die Datei öffnen und lesen, aber nicht mehr beschreiben. Ich gebe mir Debuginfromationen über die Konsole aus und danach müsste eigentlich auch alles klappen. Hier nochmal eine veränderte Version meines Codes:
if(!partition) { /* If the partition did not open, assume the storage device * is a "superfloppy", i.e. has no MBR. */ partition = partition_open(sd_raw_read, sd_raw_read_interval, sd_raw_write, sd_raw_write_interval, -1 ); if(!partition) { uart_puts_p(PSTR("opening partition failed\n")); continue; } else { uart_puts_p(PSTR("partition open \n")); } } else { uart_puts_p(PSTR("partition open \n")); /* open file system */ struct fat_fs_struct* fs = fat_open(partition); if(!fs) { uart_puts_p(PSTR("opening filesystem failed\n")); continue; } else { uart_puts_p(PSTR("filesystem open \n")); /* open root directory */ struct fat_dir_entry_struct directory; if(fat_get_dir_entry_of_path(fs, "/test", &directory)) { uart_puts_p(PSTR("fat_get_dir_entry_of_path\n")); struct fat_dir_struct* dd = fat_open_dir(fs, &directory); if(!dd) { uart_puts_p(PSTR("opening root directory failed\n")); } else { uart_puts_p(PSTR("Filesystem open \n")); uart_puts("\n"); while(fat_read_dir(dd, &directory)) { if(strcmp(directory.long_name, "test.txt") == 0) { uart_puts("found test.txt \n"); uart_puts(directory.long_name); uart_puts("\n"); struct fat_file_struct * file = fat_open_file(fs,&directory); if(!file) { uart_puts_p(PSTR("file error\n")); } else { uart_puts_p(PSTR("file ok\n")); char write[] = "test"; int data_len = strlen(write); if(fat_write_file(file, (uint8_t*) write, data_len) != data_len) { uart_puts_p(PSTR("error writing to file\n")); break; } else { uart_puts("file beschrieben \n"); fat_close_file (file); break; } } break; } } } } } } break; |
Datum:
Hallo Jan, > Hier ist das Problem: Ich weiß leider nicht mehr was ich verändert habe. Das ist immer schlecht. Wie willst Du da wissen, durch welche Änderungen die auftretenden Fehler verursacht werden? Schon mal über die Verwendung einer Versionsverwaltung nachgedacht? > Jetzt kann ich zwar die Datei öffnen und lesen, aber nicht > mehr beschreiben. Ich gebe mir Debuginfromationen über die Konsole aus > und danach müsste eigentlich auch alles klappen. Du meinst also, die Aufrufe geben alle keinen Fehler zurück, obwohl die Daten nicht in der Datei landen? Hast Du vielleicht vor dem Abziehen der Karte ein sd_raw_sync() vergessen? > Hier nochmal eine veränderte Version meines Codes: Hänge lange Quelltexte bitte als Datei an Dein Posting an. Das würde die Übersichtlichkeit sehr steigern und hoffentlich auch der Code-Formatierung zugute kommen. Viele Grüße, Roland
Datum:
Hallo Roland, > Das ist immer schlecht. Wie willst Du da wissen, durch welche Änderungen > die auftretenden Fehler verursacht werden? Schon mal über die Verwendung > einer Versionsverwaltung nachgedacht? ich war wohl auf Anhieb so begeistert, das sowohl Hardware als auch Software funktionieren, dass ich vom funktionierenden Quellcode kein Backup gemacht habe. Ich habe den Fehler gefunden. Ich hab beim "rumbasteln" wohl die sd_raw_sync() Funktion gelöscht. Jetzt funktioniert alles einwandfrei. Vielen Dank für deine Hilfe und den tollen Quellcode
Datum:
Nachdem bei meinem Atmega32 alles funktioniert hat, wollte ich den SD-Reader an ein AT90CAN128 anschließen. Im Vergleich zum Atmega32 hat dieser 8MHz statt 14,..Mhz Im Code habe ich F_CPU und die Ports abgeändert. Jetzt tauchen folgende Probleme auf. Die Karte wird nicht immer auf Anhieb erkannt, erst nach einem Reset. Ich erstelle mehrere Files, aber es scheint, dass die sd_raw_sync() nicht immer korrekt ausgeführt wird. Erst nach ein paar Resets, befinden sich die Daten auch auf der Karte. Hat jemand schonmal dieses Problem gehabt?
Datum:
MoinMoin, kann es sein, dass die letzten Versionen SRAM-Probleme bei einem Mega168 verursachen? In meinem Programm funktioniert alles hervorragend bis dann fat_create_file (und dort drin speziell fat_read_dir) aufgerufen wird. Der Mega resettet sich in dem Augenblick... Bis auf das Pinning habe ich eigentlich alle Einstellungen in den Headerfiles so belassen, wie im Orginal. Hat es jemand auf einem Mega168 am laufen? Uwe
Datum:
MoinMoin, habe mir gerade den Thread in Ruhe durchgelesen (war gestern abend nach endlosen Probieren zu spät dafür...) und gesehen, dass es scheinbar wirklich ein SRAM-Problem auf dem Mega168 sein wird. An dem Board, mit welchem ich gerade rumexperimentiere, ist noch ein LCD via TWI abgeschlossen, dafür aber kein UART ... Hmm, gibt es eine Möglichkeit mit ein paar Einstellungen den SRAM-Verbrauch ein wenig zu minimieren, um doch Rolands Routinen auf einem Mega168 zu verwenden. Ziel ist es eigentlich einen kleinen Datenlogger (Datenquellen via TWI eingebunden) aufzubauen. Grüße & Danke Uwe
Datum:
Kurze Frage, hab ich das richtig verstanden - die SD-Karte geht nur in Verbindung mit externem RAM ? Geht das nicht auch ohne?
Datum:
@Jan > Die Karte wird nicht immer auf Anhieb erkannt, erst nach einem Reset. Stabile Spannungsversorgung? Ausreichende Leistung? > Ich erstelle mehrere Files, aber es scheint, dass die sd_raw_sync() > nicht immer korrekt ausgeführt wird. Erst nach ein paar Resets, befinden > sich die Daten auch auf der Karte. Treten Fehler auf? Wenn ja welche? Wird der Controller plötzlich neu gestartet? @Uwe > kann es sein, dass die letzten Versionen SRAM-Probleme bei einem Mega168 > verursachen? In meinem Programm funktioniert alles hervorragend bis dann > fat_create_file (und dort drin speziell fat_read_dir) aufgerufen wird. > Der Mega resettet sich in dem Augenblick... Könnte durchaus sein, zumal fat_read_dir() ziemlich Stack-intensiv ist. Falls der "init"-Befehl benutzt wird, gibt es in der aktuellen Version auch noch ein kleines Speicherleck. Zugegebenerweise habe ich die letzten Releases nicht mehr explizit auf einem mega168 getestet. Mittlerweile betrachte ich das ganze als Universal-Library, die nicht mehr an eine bestimmte MCU gebunden ist. Möglichkeiten zur RAM-Verbrauchsminimierung: - FAT32/SDHC ausschalten - FAT_FS_COUNT, FAT_FILE_COUNT, FAT_DIR_COUNT minimieren - Länge von fat_dir_entry_struct.long_name reduzieren - Länge des Befehlszeilenpuffers reduzieren (main.c, ca. Zeile 295) - Beispielprogramm abspecken - LFN-Unterstützung abschalten (erst im nächsten Release) Viele Grüße, Roland
Datum:
Hallo SD-Karten User von RR, es haben ja schon einige einen Datenlogger gebaut. Ich möchte mit einem Atmega644 von der seriellen Schnitstelle von einem GPS Modul eine kontinuierliche Sequenz auf die SD Karte loggen. Wie macht man das am geschicktesten, dass die Karte eine lange lebensdauer hat? ...Am Anfang einen entsprechend grossen File erzeugen ...while (512K voll) dann schreiben... ...nur 512K Blöcke schreiben? ...sd_raw_sync() ...bei erreichen vom File Ende ==> Neuen File allokieren? ...??????? Könnte bitte jemand seinen funktionierende (Dauer)-Logger Anwendung einstellen? MfG Achim
Datum:
Roland Riegel schrieb: > Könnte durchaus sein, zumal fat_read_dir() ziemlich Stack-intensiv ist. > Falls der "init"-Befehl benutzt wird, gibt es in der aktuellen Version > auch noch ein kleines Speicherleck. Huch, jetzt machst Du mir aber richtig Angst. Ich benutze die vorletzte Version seit einigen Wochen im Dauereinsatz. Gilt das dort auch, und welches "init" meinst Du, etwa sd_raw_init()? Mit einem Dragon habe ich mir den SRam via JTAG auf dem Mega128 mehrmals in der Testphase angeguckt. Das komplette SRam beim Reset mit einem Bytemuster beschrieben, ein paar Stunden laufen lassen, dann nochmal nachgeschaut. Da waren immer locker 2k frei. Es gab(gibt) einige Auffälligkeiten, die ich meinem eigenen Zeugs zugeordnet hatte aber nie richtig erkären konnte. Wenn Du möchtest, versuche ich der Sache nochmals tiefer auf den Grund zu gehen. Torsten
Datum:
Die Spannungsversorgung ist stabil und die Leistung müsste auch ausreichend sein. Beim Debuggen gibt es keine Fehlermeldungen. Alles scheint ganz normal zu sein, nur das sich nachher keine Daten auf der Karte befinden, bzw. nur ab und zu die Daten gespeichert werden. Ich gebe mal davon aus, dass zumindest die Hardware in Ordnung ist, denn mit einem anderen SD-Kartenprojekt funktioniert alles einwandfrei. Rein theoretisch hätte es ja reichen müssen, FCPU und die Ports zu ändern.
Datum:
@Torsten > welches "init" meinst Du, etwa sd_raw_init()? Den Befehl der UART-Kommandozeile aus main.c. Das Verzeichnis-Handle wird bei "init" nicht geschlossen. > Mit einem Dragon habe ich mir den SRam via JTAG auf dem Mega128 mehrmals > in der Testphase angeguckt. Das komplette SRam beim Reset mit einem > Bytemuster beschrieben, ein paar Stunden laufen lassen, dann nochmal > nachgeschaut. Da waren immer locker 2k frei. Mit nem ATmega128 ist das auch kein Problem. Nur die 1k von den mega8/88/168 sind halt recht knapp. Der Code selbst sollte mittlerweile ziemlich ausgereift sein. > Es gab(gibt) einige Auffälligkeiten, die ich meinem eigenen Zeugs > zugeordnet hatte aber nie richtig erkären konnte. Wenn Du möchtest, > versuche ich der Sache nochmals tiefer auf den Grund zu gehen. Wenn Du möchtest, gerne. Gehöre mittlerweile aber nicht mehr den Studenten an, deshalb ist die Zeit eher begrenzt. @Jan > Ich gebe mal davon aus, dass zumindest die Hardware in Ordnung ist, denn > mit einem anderen SD-Kartenprojekt funktioniert alles einwandfrei. Wieso gehst Du davon aus, dass die Hardware in Ordnung ist, wenn die Software nahezu die gleiche geblieben ist, es aber bei der einen Hardware funktioniert und bei der anderen nicht? Schon mal mit mehreren Karten probiert? Grüße, Roland
Datum:
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?"
Datum:
Hallo Herr Riegel,danke für Ihre Librarys. In Ihrem Beitrag steht, dass Sie die Beschreibung des Mini-Shells geschrieben haben. Leider kann ich die weder auf Ihrer Seite noch in der beigefügten Dateien finden. Ich werde mich sehr freuen, wenn Sie mir einen Hinweis geben, wo sie zu finden ist. MFG Vladimir
Datum:
Hallo, Ich habe die aktuelle Version auf einen ARM7 von Atmel portiert. Läuft fast alles, FAT16, FAT32 und auch SDHC Karten werden problemlos erkannt. Ein einziges Problem kann ich nicht nachvollziehen: Legt man eine neue Datei an (so dass im Verzeichnis die Clusterposition noch auf Null steht) und versucht dann, in diese zu schreiben, so stürzt der Kontroller ab. Soweit ich herausgefunden habe, im Moment des "Return" der SPI-Schreibroutine. Dabei ist es unabhängig davon, ob FAT16 oder FAT32 benutzt wird. Vorgehensweise: "touch datei.txt" ->OK, "sync"->OK, "write datei.txt 0" -> "< Texteingabe+Enter" -> Absturz. Nach Neustart ist die Datei weiterhin leer und es wurde kein Startcluster im Verzeichnis angelegt. Liegt bereits eine Datei mit Inhalt vor, dann kann diese problemlos beschreiben bzw. geändert werden. Die Frage ist, hat das schon jemand mit AVR erfolgreich getestet? Bin mir nicht sicher, ob es ein Bug ist, oder ob es an der Portierung auf den ARM (wg. 32Bit Architektur) liegt. Da aber alle anderen Funktionen gehen, tippe ich eher auf einen Bug. Danke und Gruß Joachim
Datum:
Joachim schrieb: > Soweit ich herausgefunden habe, im Moment des > "Return" der SPI-Schreibroutine. Sehr unwahrscheinlich, dass das ein Fehler in der Library ist. Die SPI-Schreibroutine ist hardwareabhängig und damit wohl von Dir abgeändert worden. Zudem spricht ein Absturz beim return stark für einen Pufferüberlauf auf dem Stack. Gruß, Roland
Datum:
Hi Roland, Vielen Dank für die Antwort. Ja, die SPI-Routine ist natürlich für den ARM7 umgeschreiben. Funktioniert ja auch, außer in diesem einen Fall beim Schreiben einer leeren Datei. Stacküberlauf schließe ich mal nicht aus. Daran dachte ich auch schon. Wollte nur sichergehen, dass ich nicht am falschen Ende suche. Zwar gehe ich davon aus, dass der ARM mehr Stack zur Verfügung hat als ein ATMEGA, weil 64K RAM, aber vielleicht habe ich was in der Startup.c übersehen. Muss ich mal untersuchen. Gruß Joachim
Datum:
Hi, ich bin schon seit Tagen am versuchen eine SD-Karte zu beschreiben, ohne erfolg :( Mein Schaltkreis ist folgender: http://bildupload.sro.at/p/328495.html Wie man sieht, nutze ich einen Mega32. Das alles habe ich auf eine eigene Platine geätzt - Verbindungen bestehen alle, daran liegt es also nicht. Spannungen sind exakt 5V und an der SD-Karte 3,32V. Daher geh ich davon aus, das es Software-seitig ein Problem gibt. Folgende main.c hab ich geschrieben: http://darki89.bplaced.net/files/main.txt Im grunde besteht die Datei aus zusammenkopierten Teilen der Beispieldatei. Jedoch scheitert der Controller bereits an der Stelle wo die Partition geöffnet werden soll, die LED (fehleranzeige) geht an. Die Abfrage auf den Schreibschutz der Karte habe ich geändert, da der Schieber an der Karte leider fehlt: #define configure_pin_available() #define configure_pin_locked() #define get_pin_available() 0 #define get_pin_locked() 0 Außerderm habe ich SD_RAW_WRITE_SUPPORT auf 1. Fat32 und SDHC habe ich aus. Als Karte verwende ich eine alte 64MB FAT formatierte karte, mit einer Zuordnungsgröße von 4096Byte. Ich hab den Thread hier schon ein wenig durchforstet und versucht, die Zeilen mit der maximalen SD-Geschwindigkeit auszukommentieren, brachte keine Besserung. Die Sache mit dem Schreibschutz, was ich auch hier gefunden hab, habe ich oben ja schon erwähnt. Mehr sachen habe ich leider nicht finden können, da der Thread einfach verdammt groß ist. Hat jemand eine Idee? Leider habe ich kein Debug-Interface wie JTAG oder was über RS232 (hab so nen anschluss garnichmehr). Danke schonmal :)
Datum:
@Dschadu Versuch doch mal erst die rudimentären Funktionen wie sektor schreiben und lesen zu testen. Schreib z.B. eindach einen Textstring auf ein paar 100 Sektoren, lies sie dann und vergleiche. Das muß bis aufs letzte Bit stimmen, bevor du da ein Filesystem verwenden kannst. Um eine serielle Schnittstelle zu debug-Zwecken (mit printf o.ä.) wirst du da nicht herumkommen. p.s. Ich hab 2Wochen mit meinem ADUC7024 gekämpft bis alles gut gelaufen ist. Grüße Gebhard
Datum:
Hallo Dschadu,
Les Dir mal die FAQ durch, insbesondere
http://www.roland-riegel.de/sd-reader/faq/#faq_socketcdcl
Dann sollte es auch mit dem Schreiben funktionieren...
Gruß,
Roland
Datum:
Angehängte Dateien:Hallo, erst ein mal großes Lob, denn der Code tut einbahnfrei. Allerdings nur solange ich dein Bsp. Programm nutze. Ich vermisse Methoden die den ganzen Kram machen den du direkt in der main() machst also etwas in diese richtung:
uint8_t sd_init(); void sd_ende(); uint8_t sd_write(char* file, char* data, uint8_t length, uint32_t pos, uint8_t whence); uint8_t sd_read(char* file, char* erg, uint8_t length, uint8_t max_length, uint32_t pos, uint8_t whence); uint8_t sd_cd(char* dir); uint8_t sd_deletfile(char* file); uint8_t sd_creatfile(char* file); uint8_t sd_creatdir(char* dir); uint8_t sd_print_disk_info(); |
Sodass ich nur diese Methoden brauche. Ich versuche jetzt schon seit mehr als 2 Woche etwas dergleichen zu machen. Klappt leider nicht. nun gut. ich hab jetzt nochmal was anderes probiert mit dem ich mich abfinden könnte wenns täte :( Diese Version habe ich angehängt. Ich hab dabei nur die main.c verändert Zu den Fehlern: es wird nur am Uart nur "Start" und "init" ausgegeben dies allerding ständig der macht also irgendwo im init teil nen reset. Wenn ich allerdings die Schleife while(idle) -sammt Inhalt- auskommentiere dann initialisiert er ganz normal und gibt mir die Disk Info aus. Ich hab dann mal noch verschiedene sachen ausprobiert mit if oder mit weniger schleifen ... jedesmal kam was anderes raus. aber nie das was sollte. Diese fehler lassen darauf schließen, dass der Compiler misst macht. Und das gefällt mir garnicht! Nebenbei ich benutze nen ATmega168 @ 18,432MHz und eclipse mit AVR-plugin und WinAVR ich bin langsam am verzweifeln und kurz davor an die Decke zu gehen. Hat jemand ne Idee was ich falsch mach oder Methoden wie ich sie am Anfang beschrieben hab gemacht? Wäre sehr dankbar über Hilfe gruß Matze
Datum:
Hallo Matze, Matze schrieb: > Ich vermisse Methoden die den ganzen Kram machen den du direkt in der > main() machst > also etwas in diese richtung: > [...] > Sodass ich nur diese Methoden brauche. > > Ich versuche jetzt schon seit mehr als 2 Woche etwas dergleichen zu > machen. Klappt leider nicht. Was genau klappt denn nicht? Die von Dir gewünschten Funktionen sollten aus den bereits vorhandenen relativ schnell implementiert werden können. Generell sollte Dir aber bewusst sein, dass bei jedem Aufruf der von Dir skizzierten Funktionen z.B. die Dateien neu geöffnet und geschlossen werden müssen, was einiges an Overhead bedeutet sowie Performance und Flexibilität nimmt. > Zu den Fehlern: > es wird nur am Uart nur "Start" und "init" ausgegeben dies allerding > ständig der macht also irgendwo im init teil nen reset. > > Wenn ich allerdings die Schleife while(idle) -sammt Inhalt- > auskommentiere dann initialisiert er ganz normal und gibt mir die Disk > Info aus. > > Ich hab dann mal noch verschiedene sachen ausprobiert mit if oder mit > weniger schleifen ... jedesmal kam was anderes raus. aber nie das was > sollte. > > Diese fehler lassen darauf schließen, dass der Compiler misst macht. Und > das gefällt mir garnicht! Nein, der Compiler ist höchstwahrscheinlich unschuldig. > Nebenbei ich benutze nen ATmega168 @ 18,432MHz > und eclipse mit AVR-plugin und WinAVR Der ATmega168 ist ziemlich knapp bemessen, vor allem bzgl. verfügbarem RAM. Du hast zu Beginn von main() einige neue Variablen eingeführt, die insgesamt ca. 60 Bytes benötigen. Das ist verhältnismäßig viel und könnte zur Kollision von Stack und Heap führen, wodurch allerhand undefinierte und merkwürdige Sachen zustande kommen. Siehe dazu auch die letzte FAQ unter http://www.roland-riegel.de/sd-reader/faq/ Reduziere mal testweise den Funktionsumfang in main() und überprüfe die Konfigurationen in sd-raw_config.h und fat_config.h. Schalte SDHC, FAT32, Zeitstempel und zur Not auch Schreibzugriff aus, und teste erstmal damit. Gruß, Roland
Datum:
Hallo zusammen, ich habe mir den Beitrag hier duchgelesen. Jedoch habe aber immer noch eine Frage, die mich beschäftigt. So wie ich es verstanden habe, ist für die Unterstützung der FAT-Routinen eine SD-Karte nötig, die mit einer Blockgröße von 512 Byte formatiert ist. Ist es möglich, mit einem Atmel Mikrocontroller eine angeschlossene SD-Karte derart zu formatieren? Wenn ja, wie wird es umgesetzt? Mit freundlichen Grüßen Thomas
Datum:
Hallo Thomas, > So wie ich es verstanden habe, ist für die Unterstützung der > FAT-Routinen eine SD-Karte nötig, die mit einer Blockgröße von 512 Byte > formatiert ist. Nein. Die Blockgröße von 512 Bytes hat nichts mit FAT zu tun. Es geht dabei um die Blöcke, mit der die SD-Karten angesteuert werden. Den Karten ist es egal, mit welchem Dateisystem die Daten verwaltet werden. Du kannst also beliebig erstellte FAT-Dateisysteme verwenden, mit beliebiger Clustergröße ("Cluster" -> FAT16/32, "Block" -> Datenträger). Gruß, Roland
Datum:
Hallo Roland, ok dann habe ich das mit der Blockgröße missverstanden. Aber ist es nicht so, das ich eine SD-Karte unter Windows nur mit bestimmten Clustergrößen formatieren kann. Um aber mit einem Amtel-Controller die FAT zu realisieren, wird so weit ich weis, meistens die Clustergröße von 512 Byte verwendet. So kann dann ein gelesener Cluster direkt ins RAM geschrieben werden. OK, mit einem entsprechenden Controller kann man auch Cluster von 1024 Byte lesen und im RAM puffern, aber z. B. mit einem ATmega16 ist das nicht möglich. Wenn dem so ist, muss diese SD-Karte ja dementsprechend (Clustergröße von 512 Byte) formatiert werden. Ist dieses formatieren denn auch mit einen Atmel-Controller realisierbar? Also kann ich mir das formatieren der Karte am PC durch eine Funktion im Mikrocontroller ersetzen? Wenn ja, wie wird es umgesetzt? Mit freundlichen Grüßen Thomas
Datum:
Servus Thomas, Thomas schrieb: > Aber ist es nicht so, das ich eine SD-Karte unter Windows nur mit > bestimmten Clustergrößen formatieren kann. Jein. Die Clustergröße wird automatisch so gewählt, dass mit den max. ca. 65000 Clustern von FAT16 der ganze Datenträger abgedeckt werden kann. > Um aber mit einem Amtel-Controller die FAT zu realisieren, wird so weit > ich weis, meistens die Clustergröße von 512 Byte verwendet. Nein. Sonst könntest Du, wie oben angedeutet, mit FAT16 nur maximal ca. 32MB verwalten. > So kann dann > ein gelesener Cluster direkt ins RAM geschrieben werden. > OK, mit einem entsprechenden Controller kann man auch Cluster von 1024 > Byte lesen und im RAM puffern, aber z. B. mit einem ATmega16 ist das > nicht möglich. Doch. Es sagt ja niemand, dass man immer einen ganzen Cluster einlesen muss. Bei den SD-Karten wird zwar immer ein ganzer Block (512 Bytes) eingelesen, aber es ist egal, ob das nun ein ganzer Cluster ist oder nicht. > Wenn dem so ist, muss diese SD-Karte ja dementsprechend (Clustergröße > von 512 Byte) formatiert werden. Dem ist nicht so. Das Cluster-Prinzip ist eine Abstraktion des Dateisystems, nicht des Kartenzugriffs. > Ist dieses formatieren denn auch mit einen Atmel-Controller > realisierbar? Theoretisch wohl schon, mit meiner Bibliothek aber nicht. > Also kann ich mir das formatieren der Karte am PC durch eine Funktion im > Mikrocontroller ersetzen? S.o. Generell würde ich aber sagen, dass das Formatieren am PC einfacher ist und Code auf dem Mikrocontroller spart. > Wenn ja, wie wird es umgesetzt? Naja, mann müsste eben entsprechende Header-Informationen und mind. eine FAT an den Anfang der Partition schreiben und ein Wurzelverzeichnis anlegen. Gruß, Roland
Datum:
hallo wollten den neuesten code 2009-03-30 von roland rieger in avr studio 4.14 für einen mega328p compilieren. es kommt dann folgende fehlermeldung: ../sd_raw_config.h:107:6: error: #error "no sd/mmc pin mapping available!" ich denke der fehler liegt daran, dass ich im avr studio nur den mega328p (den mega328 gibt es nicht) auswählen kann jedoch im programm der mega328 definiert ist. wenn ich defined(_AVR_ATmega328_) auf defined(_AVR_ATmega328P_) ändere bekomme ich jedoch fehlermeldungen wie zb ../sd_raw.c:184: error: 'PB2' undeclared (first use in this function) ../sd_raw.c:184: error: (Each undeclared identifier is reported only once ../sd_raw.c:184: error: for each function it appears in.) ../sd_raw.c: In function 'sd_raw_available': ../sd_raw.c:341: error: 'PC4' undeclared (first use in this function) ../sd_raw.c: In function 'sd_raw_locked': ../sd_raw.c:352: error: 'PC5' undeclared (first use in this function) ../sd_raw.c: In function 'sd_raw_read': ../sd_raw.c:467: error: 'PB2' undeclared (first use in this function) ../sd_raw.c: In function 'sd_raw_write': ../sd_raw.c:714: error: 'PB2' undeclared (first use in this function) ../sd_raw.c: In function 'sd_raw_get_info': ../sd_raw.c:858: error: 'PB2' undeclared (first use in this function) make: *** [sd_raw.o] Error 1 Build failed with 8 errors and 0 warnings... kann vielleicht jemand helfen?! WinAVR-20080610 (AVR Libc 1.6.2 ) avrstudio 4.14 verwende ich mfg
Datum:
Angehängte Dateien:Lowtzow .... schrieb: > wollten den neuesten code 2009-03-30 von roland rieger in avr studio > 4.14 für einen mega328p compilieren. > es kommt dann folgende fehlermeldung: ../sd_raw_config.h:107:6: error: > #error "no sd/mmc pin mapping available!" > > ich denke der fehler liegt daran, dass ich im avr studio nur den > mega328p (den mega328 gibt es nicht) auswählen kann jedoch im programm > der mega328 definiert ist. wenn ich defined(_AVR_ATmega328_) auf > defined(_AVR_ATmega328P_) ändere bekomme ich jedoch fehlermeldungen Die Unterstützung für den mega328 ist im aktuellen Release versaut. Da war ich etwas vorschnell, tut mir Leid. Nach dem Anwenden des Patches im Anhang sollte es funktionieren. Gruß, Roland
Datum:
Hallo Roland, in Deinem aktuellen Schaltplan werden CD und WP mit Pullup gegen VCC (=5V) gezogen. Ist das so richtig, oder sollten es nicht 3.3V sein? Gruss, Pete
Datum:
Hallo Pete, Ja das ist korrekt, denn CD und WP sind ja nur Kontakte des Kartenhalters, damit der uC erkennen kann, ob eine Karte gesteckt ist und ob deren Schreibschutzschalter aktiv ist. Falls Dein Sockel diese Kontakte nicht hat, bitte den Code so abändern wie in der FAQ auf meiner Homepage beschrieben. Gruß, Roland
Datum:
Angehängte Dateien:Hallo zusammen! Nach längerer Zeit habe ich mal wieder ein neues sd-reader-Release erstellt (siehe Anhang). Neben Bugfixes enthält es auch zwei neue Features. - Optional verzögerte Aktualisierung von Verzeichniseinträgen. Dies kann die Schreib-Performance in vielen Szenarios erhöhen. - Unterstützung für lange Dateinamen (LFN) ist jetzt abschaltbar. - Ignoriere LFN-Einträge ohne zugehörigen 8.3-Namen. - Ignoriere LFN-Einträge, welche nicht zur 8.3-Prüfsumme passen. - Beschleunigung der Suche nach einem freien Cluster (in einigen Fällen). - Speicherleck beim Uart-Kommando "init" behoben. - Korrektur der ATmega328P-Pinzuordnungen, andere AVR picoPower-Varianten hinzugefügt. Den zugehörigen Patch, andere Einzelheiten, FAQs, neue Benchmarks mit verzögert aktualisierten Verzeichniseinträgen und Dokumentation gibts wie immer auf meiner Homepage: http://www.roland-riegel.de/sd-reader/ Viele Grüße, Roland
Datum:
Hallo Roland, zuerst mal ein fettes danke für deine arbeit! hammer!!!! ich hätte jedoch eine frage: wenn ich ein file erstelle und darin messwerte abspeichere erkennt er mir kein enter zb.: 2010-01-10 12:32:11;14,532;l/s;29328398.2938;m3<ENTER> 2010-01-10 12:32:12;14,532;l/s;29328398.2938;m3<ENTER> 2010-01-10 12:32:13;14,532;l/s;29328398.2938;m3<ENTER> 2010-01-10 12:32:14;14,532;l/s;29328398.2938;m3<ENTER> 2010-01-10 12:32:15;14,532;l/s;29328398.2938;m3<ENTER> 2010-01-10 12:32:16;14,532;l/s;29328398.2938;m3<ENTER> ich habe zwar einen code hinzugefügt das er mir bei einem # Zeichen ein Enter durchführt. es wäre vielleicht gut dies in einem code zu implementieren oder gibt es schon sowas und ich habs überlesesn. lg hannes
Datum:
Hallo Hannes, Hannes schrieb: > wenn ich ein file erstelle und darin messwerte abspeichere erkennt er > mir kein enter Meinst Du den "write"-Befehl auf der UART-Kommandozeile? Das stimmt, der schreibt keine Zeilenumbrüche. Aber er ist ja auch nicht dafür gedacht, von einer realen Anwendung verwendet zu werden. Aber wenn Du es unbedingt brauchst, kannst Du die Implementierung in main.c ja entsprechend abändern. Gruß, Roland
Datum:
danke roland für deine antwort. schon mal an den ernstfall gedacht wenn unterm schreiben die spannung einbricht (gerade im akku oder batterie betrieb von einem gerät mit deiner software) ? was ich immer bei fat etc. datenspeicherung bedenke, gerade im batterie betrieb, das das system crasht vielleicht kannst du mir was dazu sagen Viele Grüße Hannes
Datum:
Hallo Hannes, Hannes schrieb: > schon mal an den ernstfall gedacht wenn unterm schreiben die spannung > einbricht (gerade im akku oder batterie betrieb von einem gerät mit > deiner software) ? > was ich immer bei fat etc. datenspeicherung bedenke, gerade im batterie > betrieb, das das system crasht > > vielleicht kannst du mir was dazu sagen Nun ja, was soll ich da von Seiten der Library noch groß tun? Gegen einen Ausfall der Spannungsversorgung kann man nichts machen, das ist aber bei allen Dateisystemen so. Natürlich gibt es Journaling-Systeme, die nach einem Crash das System möglichst schnell wieder herstellen, gegen einen Datenverlust schützen sie aber auch nicht. Bei meiner Library habe ich zwar darauf geachtet, dass nur zu möglichst wenigen und möglichst kurzen Zeitpunkten das Dateisystem inkonsistent wäre. Aber auch das bewahrt nicht vor Datenverlust. Allerdings ist ja im Falle von batteriebetriebenen Geräten nicht von einem plötzlichen Spannungsausfall, sondern eher von einem langsamen Abfall auszugehen. Wenn Du also einen Brown-Out-Detektor verwendest und bei dessen Aktivierung ein sd_raw_sync() vornimmst sowie sämtliche weiteren Schreibzugriffe unterbindest, sollte das genügen. Gruß, Roland
Datum:
herzlichen dank für den hinweis! das mit dem brown out ist super Viele Grüße Franz
Datum:
Angehängte Dateien:Ich raff es nicht, es wird keine SD-Karte mit beiliegender Schaltung und der neuen Library von Roland erkannt (Rückgabewert bei CMD_GO_IDLE_STATE ist 0x1FF). - ATMega644P läuft mit 8 Mhz intern (sonst 20 Mhz) - Compiliert mit Os und O1 - 47µF und 100nF direkt hinter dem Kartenslot - ISP nicht angeschlossen - LED gegen CS ist nicht bestückt - Pullup an DO ist 165K (ist das zu groß?) - WP und CD werden nicht genutzt - sd_raw_available() fest auf return 1 gesetzt - sd_raw_locked() fest auf return 0 gesetzt - SD-Karte wird mit 3.29V (gemessen) versorgt - Wartezeit bis sd_init ca. 3 Sekunden (I2C-Display wird initialisiert) Ich habe 4 SD-Karten (16-64MB) probiert, alle funktionieren nicht. Auch ein Formatieren der Karten in einer Fotokamera hilft nicht. Bin für jeden Tipp dankbar...
Datum:
Habe gerade mal PB3-7 auf "on" gesetzt (PORTB |= (1<<PB3) etc.) und siehe da, an PB3 liegen 4,97V an, an PB4,5,7 nur 0,63V und an PB6 nur 4,65V. Alles ohne Karte gemessen. Merkwürdig...
Datum:
Hallo Pete! Bist Du die FAQ auf meiner Homepage durchgegangen? Ansonsten: - Der MCP1700 könnte mit max. 250mA etwas zu schwach sein. - An den Ein- und Ausgängen der Spannungsregler jeweils 100nF vorsehen. - Wie lang sind die 3V3/MISO/MOSI/SS-Leitungen? - Hast Du ein Oszilloskop, um diese Signale anzuschauen? Interessant wäre auch der 3V3-Verlauf während dem Anstecken der Karte. - Verwendest Du ein ausreichend dimensioniertes Netzteil? - 16MB-Karten sind mit FAT12 formatiert, die kannst Du mit meinem Code nur Raw ansprechen (ohne FAT). Gruß, Roland
Datum:
Pete K. schrieb: > an PB3 liegen 4,97V an Ok. > an PB4,5,7 nur 0,63V Das ist schlecht. > an PB6 nur 4,65V Na gut, da treibt der 5V-Port-Pin über den Pullup nach 3.3V. Sollte bei 165k gefühlsmäßig aber eigentlich auch höher liegen. Hast Du Dein Layout/Aufbau kontrolliert? Anderen Controller ausprobiert? Gruß, Roland
Datum:
Hallo Roland, hier ein paar Antworten: - Die Leitungen sind etwa 6cm lang. - 3V3 Leitung ist kürzer - Leider habe ich kein Oszi, ich kann nur per RS232 und Multimeter "debuggen" - Das Netzteil schafft 600mA bei 7,8V laut Aufdruck - Ich habe jeweils eine 16MB, 32MB und 64Mb SD-Karte sowie eine 16Mb MMC-Karte. Eine 8GB SDHC will ich da erst einmal noch nicht testen :-) - Mit dem Multimeter kann ich beim Einstecken der Karte auf der 3V3 Leitung keinen Spannungseinbruch erkennen. Ist aber wahrscheinlich auch zu träge dafür. Anderen Controller, auch wenn das Flashen per ISP geht? Da werden ja auch keine anderen Pins benutzt... Anbei das Layout, Massefläche habe ich ausgeblendet.
Datum:
Angehängte Dateien:Beim Bearbeiten kann man keine Datei anhängen.
Datum:
A propos Pullup: Ich weiß dass einige Leute hier empfehlen, einen solchen zu verwenden. Bisher habe ich diesen bei meinen Schaltungen aber nie verwendet. Gruß, Roland
Datum:
Ein anderer Controller bringt die gleichen Ergebnisse. Die CS-Leitung hat 1k8 Ohm gemessen vom µC Pin zum Slot. Stimmt soweit.
Datum:
Pete K. schrieb: > Ein anderer Controller bringt die gleichen Ergebnisse. > > Die CS-Leitung hat 1k8 Ohm gemessen vom µC Pin zum Slot. Stimmt soweit. Hmm, bin da dann auch ein bisschen ratlos. - Reset wirklich erst nach Abnehmen des ISP-Adapters losgelassen? - Neues von Deinem Pegeltest? Pegelstände auf SD-Seite? - sd_raw_config.h nochmal kontrolliert? - Pullup an MISO mal weglassen? - Liest der uC tatsächlich anliegende MISO-Werte? Test mit Draht ohne Karte? Ähnliche Experimente? Gruß, Roland
Datum:
Weil auf Deiner Schaltung einige Peripherie zu sehen ist: läuft der sd-reader so wie er ist oder hast schon einige Sachen für Deine Hardware eingebaut?
Datum:
Die Peripherie läuft, nur die SD-Karte nicht :-< Ich habe jetzt die Pullups ausgelötet und nur die SD-Reader Sourcen benutzt. Leider klappt es immer noch nicht. Parallel habe ich auf einem Steckbrett und einem SD-Kartenslot auf Lochraster auch mit Spannungsteiler getestet, dort kann ich eine SD-Karte erkennen (Disk-Info wird ausgegeben). Insofern ist die Software ok, da habe ich aber auch wirklich nicht dran gezweifelt :-) Immerhin habe ich jetzt eine Karte, welche sicher funktioniert. Aber irgendwo ist noch der Wurm drin....
Datum:
Dann kann es doch nur noch an der Platine oder den Bauteilen liegen. Ich hatte z.B. ein Problem mit den Anschlüssen an meinem Kartenhalter. Wenn man die weiter verfolgte sah alles sehr merkwürdig aus. Habs einfach durchgeklingelt.
Datum:
Der Kartenhalter ist gespiegelt (ggrrrmmmppfff), da muss ich wohl erst einmal eine neue Platine machen. Vielen Dank für eure Mithilfe!
Datum:
Danke :) > Der Kartenhalter ist gespiegelt (ggrrrmmmppfff), da muss ich wohl erst > einmal eine neue Platine machen. Bei dieser Gelegenheit könntest Du auch viele unnötige pullups rauswerfen, z.B. um den Drehencoder und JP14..17. Schalte einfach die internen des AVR ein denn die Widerstandswerte sind nicht kritisch. Damit gewinnst Du bestimmt Platz um die 3k3/1k8 Spannungsteiler als Pegelwandler für die SD-Karte durch etwas anständiges zu ersetzen. Z.B durch einen 74HC4050B den ich auch erfolgreich verwende. Kostet nur ein paar Cent.
Datum:
Bei mir funktioniert das Programm jetzt wunderbahr, danke! :)
Datum:
Hallo ich habe eine Frage zur maximal möglichen Anzahl an Dateien, die ich in einem Ordner auf der SD-Karte speichern kann. Ich habe ein Testprogramm geschrieben, dass fortlaufend Dateien anlegt. Bei einer 1GB Karte kann ich 255 Dateien in einem Ordner anlegen. Bei einer 2GB Karte sind es 511 Dateien. Beide Karten mit FAT16 formatiert (Panasonic SDFormater). Danach habe ich die 1GB Karte mit FAT32 formatiert (Windows). Ich konnte dann nur 63 Dateien in einem Ordner speichern. Weis jemand von was die maximale Dateianzahl abhängig ist, bzw. wie man die Anzahl erhöhen kann?
Datum:
Hallo Kai, Kai J. schrieb: > Weis jemand von was die maximale Dateianzahl abhängig ist, bzw. wie man > die Anzahl erhöhen kann? Generell ist die Anzahl der Dateien nur beim Wurzelverzeichnis von FAT16 beschränkt, bei FAT32 bzw. bei Unterverzeichnissen allgemein gibt es keine Beschränkung. Was passiert, wenn Du keine Dateien mehr anlegen kannst? Wie äußert sich der Fehler? Gruß, Roland
Datum:
Hallo Roland, das Programm bleibt dann einfach hängen. Das passiert in der Funktion
fat_create_file(dd, filename, &file_entry) |
wobei filename ein char-array ist, z.B. *254.txt*. Ich habs jetzt noch mal genauer untersucht. Das Programm kommt aus der while(1) Schleife nicht mehr raus. Da drin läuft es bei mir ab der 256-ten bzw. 512-ten Datei endlos weiter. Gruß Kai
Datum:
Hallo Kai, Ich habe Dein Problem eben lokal nachvollziehen können. Es ist ein Bug, der wohl leider schon länger besteht. Er tritt auf, wenn der letzte Eintrag eines Verzeichnisses direkt vor einer Clustergrenze liegt. Werd mir mal Gedanken machen, wie man das beheben kann und mich dann in den nächsten Tagen zurückmelden. Gruß, Roland
Datum:
Angehängte Dateien:Hallo Kai, Könntest Du bitte mal den angehängten Patch auf fat.c anwenden und mir von den Ergebnissen berichten? Bei mir tritt das Problem damit nicht mehr auf. Gruß, Roland
Datum:
Hallo Roland, jetzt klappt's wunderbar. Mein Programm ist bei 1000 Dateien ohne Probleme durchgelaufen. Ich probier mal aus, ob ich noch mehr Dateien anlegen kann. Vielen Dank für die schnelle und freundliche Hilfe ;) Gruß Kai
Datum:
Hallo Kai, Danke Dir für die Rückmeldung. Die Änderung wird dann in der nächsten sd-reader-Version enthalten sein. Gruß, Roland
Datum:
Hallo Roland, vielen Dank für Deine tolle Arbeit. Meinst Du, man bekommt das auch auf einem xmega problemlos zum laufen? Hast Du so was schon mal probiert? Liebe Grüße, Hans
Datum:
Hallo Hans, Zufällig habe ich vor kurzem einen Bericht erhalten, nachdem die Bibliothek auch auf dem XMega läuft. Wenn Du mir eine private Mail schreibst, antworte ich mit den Anpassungen, die mir zugeschickt wurden. Gruß, Roland
Datum:
Hallo zusammen! zu meinem Problem: ich habe die neueste SD Library ausporbiert und in meinem Programm implementiert. Die Funktion sd_raw_init funktioniert, die Funktion sd_raw_get_info ebenfalls. rufe ich die Funktion sd_raw_read auf, kommt return 1 zurück -> soweit so gut. Ich habe den Offset 0 gewählt. Es werden aber keine Datenausgelesen, obwohl bei einem Offset = 0 der Beginn des Bootsektores des FAT Dateisystems zu sehen müsste... Gruss, Ivan
Datum:
Hallo Ivan, Ohne ein paar genauere Angaben wird Dir hier keiner helfen können. - Lese bitte die FAQ auf meiner Homepage. - Welche MCU? Welches Board? - Welche Daten werden zurückgeliefert? - Funktioniert die sd-reader Anwendung (main.c) alleine? - Relevanten Code posten? Gruß, Roland
Datum:
Angehängte Dateien:Hallo Leute,
ich habe ein problem ... mit der neuen version bekomme ich immer die
meldung
> touch hannes.txt
error creating file: hannes.txt
wenn ich den alten code stand sd-reader_source_20090330 raufspiele
gehts
sd-reader_source_20100110 bringt mit den fehler
hab den code zusätzlich angehängt falls ich wo n config fehler habe!
VIELEN DANK IN VORAUS
lg
hannes
Datum:
okay saublöder fehler ... irgendwo hats was mit dem writeprotect ... hab den bei der sd card reingegeben und nun gehts ... muss den pin negieren dann hauts auch mit dem nachbarn hin :-)
Datum:
hab aber ein problem mit der sd hc ein file anlegen geht aber sobald
ich den write befehl durchführe hängt er
> write hannes.txt 0
< es geht
error writing to file
danke für die hilfe in voraus
lg
hannes
Datum:
@Roland Das Problem habe ich nun gelöst: es lag an der Speicherkarte, eine 1Gb Speicherkarte (Typ 2.0) kann ich problemlos beschreiben und wieder lesen. Ich lese Sektor 0 (erste 512 Bytes) aus und gebe sie über UARt an den PC aus. Mache ich das mit einer 2GB Karte (2.0), kommt irgendetwas daher, jedoch nicht der Bootsektor des FAT Dateisystems, mit einem HEX-Editor habe ich das überprüft. Die beiden Speicherkarten sind von SanDisk, die 1GB Karte ist ca. 2 Jahre alt, die 2GB Karte neu. Hat deine Library ein Problem mit 2GB Karten? Gruess, Ivan
Datum:
@Hannes Nachdem da bei Dir eine Fehlermeldung auftaucht, hängt er ja wohl nicht, sondern liefert nur eine Fehlermeldung zurück. Kannst Du nachvollziehen (mittels Debugger oder in den Code eingefügter printf()s), an welcher Stelle er mit dem Fehler aussteigt? @Ivan Normalerweise hat sd-reader kein Problem mit 2GB-Karten, ich verwende hier selbst eine. Womit ich jedoch keine Erfahrung habe, sind Karten mit weniger als 4GB (also nicht SDHC), die aber der Version 2 der SD-Spezifikation folgen. Gruß, Roland
Datum:
hallo roland, werd ich machen, den fehler spuckt er nur aus wenn ich die sd hc karte rausgebe, irgendwas muss mit der sdhc sein weil er beim init sehr lange braucht. bei punkt free: "hängt" er n paar minuten und spuckt dann free: 0/0 aus. ich hab nur einen typ sdhc karte transcend. vielleicht probier ich mal ne andere aus ... muss mir die erst kaufen. sd funktioniert prima!!! liebe grüße hannes
Datum:
Hallo Hannes, Vielleicht nützt es ja schon wenn Du die Karte mal neu formatierst? Das mit dem freien Speicherplatz macht mich stutzig. Gruß, Roland
Datum:
Hallo Roland, hab´s schon ein paar mal formatiert ... vielleicht liegts am fat32 muss das am wochenende mal ordentlich durchprobieren. Viele Grüße Hannes
Datum:
Hallo Roland, mein Problem hat sich immer noch nicht gelöst! Ich beschreibe dir nun meine SW: ich rufe im Main folgenden Code auf:
int main(void) { UC ucBuffer[512] = {'H','a','l','l','l','o',' ','W','e','l','t'}; UC ucRetSD = 0; ucRetSD = sd_raw_init(); //SD Karte starten if(ucRetSD) { UART_send_String_while("\nSD init OK\n"); } else { UART_send_String_while("\nSD init failed\n"); } sd_raw_write(0x0EA16A00, ucBuffer, 512); sd_raw_sync(); ucBuffer[0] = 0; ucBuffer[1] = 0; ucBuffer[2] = 0; ucBuffer[3] = 0; ucBuffer[4] = 0; ucBuffer[5] = 0; ucBuffer[6] = 0; ucBuffer[7] = 0; ucBuffer[8] = 0; ucBuffer[9] = 0; sd_raw_read(0x0EA16A00, ucBuffer, 512); UART_send_Block_while(ucBuffer, 512); struct sd_raw_info disk_info; ucRetSD = sd_raw_get_info(&disk_info); lSize = disk_info.capacity /1024 /1024; sprintf(ucSizeString, "%u", lSize); UART_send_String_while("\noem: "); UART_send_String_while(disk_info.oem); UART_send_String_while("\nprod: "); UART_send_String_while(disk_info.product); UART_send_String_while("\nsize: "); UART_send_String_while(ucSizeString); if(ucRetSD) { UART_send_String_while("\nSD info OK"); } else { UART_send_String_while("\nSD info failed"); } UART_send_String_while("\n"); sd_raw_read(0x00, ucBuffer, 512); UART_send_String_while("\n"); UART_send_Block_while(ucBuffer, 512); if(ucRetSD) { UART_send_String_while("\nSD read OK\n"); } else { UART_send_String_while("\nSD read failed\n"); } } |
bei der Funktion sd_raw_read(0x00, ucBuffer, 512) kommt einfach nicht das heruas, was ich herauslese, wenn ich die Karte in den Reader stecke und mit dem HEX-Editor überprüfe. Die Funktion UART_send_Block_while(ucBuffer, 512); sendet jeweils ein Array mit der Länge 512Bytes ans Terminal. Muss ich irgendwie zuerst eine Startadresse auslesen, wo das Dateisystem beginnt? folgendes Kriege ich raus (Terminal): ... 0ðÀ vUª -> Das Uª (=55AA) ist interessant, da FAT "Checksumme" SD read OK Mit dem HEX-Editor lese ich auf Adresse 0 folgendes: ëXMSDOS5.0 Wo liegt der Fehler? gruss Ivan
Datum:
Der Sektor der 0x55AA endet ist der physikalisch erste Sektor der SD. Da steht die Partitionstabelle. An die kommst du unter Domesdos mit dem standard Debug.com nicht ran. (Ich kann mich erinnern dass man dafür den Symdebug = Debug.exe vom Macroassembler brauchte). Auch die Norton Utility ist da rangekommen. Was der Debug.com liefert ist der erste Sektor der DOS-Partion, aber nicht die Partitionstabelle bzw. der erste physikalische Sektor.
Datum:
@Werner B. Danke für den Tipp, habe die umfangreiche FATFS von ElmChan mit der sd_raw.c von Roland verknüpft -> funktioniert wunderbar. Die Partition bzw. den MBR wertet die FATFS aus, der Rest ist kein Problem mehr. Danke für eure Hilfe! Gruss Ivan H.
Datum:
Wollte hier nur mal danke sagen. Ich hab die Library für meinen ATxmega32 portiert und es funktioniert wunderbar.
Datum:
Hallo, ich würde gerne eine Datei mit Variablen Namen erstellen, doch leider geht es nicht. Kann mir einer helfen?
[...] char tmp_name[13]; char* name = tmp_name; name[0] = ((gps_data.tag / 10) + 0x30); name[1] = ((gps_data.tag%10) + 0x30); name[2] = '.'; name[3] = ((gps_data.monat / 10) + 0x30); name[4] = ((gps_data.monat%10) + 0x30); name[5] = '.'; name[6] = ((gps_data.jahr%2000 / 10) + 0x30); name[7] = (((gps_data.jahr%2000)%10) + 0x30); name[8] = '.'; name[9] = 't'; name[10] = 'x'; name[11] = 't'; name[12] = '\0'; static struct fat_dir_entry_struct file_entry; if(!fat_create_file(dd, tmp_name, &file_entry)) { return 1; } [...] |
Datum:
Warum schreibst Du nicht die Werte in tmp_name, wenn Du das als Variable übergibst? Versuch mal: if(!fat_create_file(dd, name, &file_entry))
Datum:
Angehängte Dateien:Hallo, ich habe 2 Probleme mit meiner SD Karte. Hintergrund: Für ein Projekt muss ich einen Datenlogger realisieren. Geloggt werden GPS Daten und verschiedene Sensoren, welche über den CAN Bus empfangen werden. Alle Daten ergeben maximal einen String von 300 Byte. Dieser String soll mit einer festen Frequenz von 50Hz geloggt werden. Prozessor ist ein AT90CAN128 mit 16MHZ. Problem 1: Leider habe ich aber schon bei 10 Hz Probleme mit der Reorganisation der Karte. Momentan schreibe ich aller 100mSec einen String von 150 Byte mit folgendem Befehl auf die Karte.
if(fat_write_file(fd, (uint8_t*) sd_buffer, strlen(sd_buffer)) != strlen(sd_buffer)) { uart1_puts("Fehler beim schreiben\n\r"); } sd_raw_sync(); |
Problem 2: Manchmal habe ich auch Probleme mit der Initialisierung von SD Karten. Die Karten arbeiten 20mal problemlos. Das bedeutet ich kann die karte auf mein Boardstecken und beschreiben und die Daten dann per PC von der Karte lesen. Und dann klappt das eine ganze Zeit lang nicht mehr. Ich kann zwar die karte initialisieren, die Kartininformation und filesystem auslesen, aber das gewünschte File nicht erzeugen oder öffnen oder bis an das fileende springen. Keine Ahnung warum, ist reinzufällig. Mein Programm findet ihr im Anhang, würde mich über jede Hilfe freuen. Schon mal vielen Dank Martin Martin Junghans
Datum:
Ich würd mal auf das Signal schauen das zu den SD Karten geht. Keine Ahnung was du für ne Anpassung machst, oder ob du überhaupt eine hast. Normalerweise läuft der MC auf 5v die Karte aber auf 3.3V. Wenn du da einen Spannungsteiler (Widerstände) hast, ist das bei höheren Übertragungsfrequenzen fatal. Wenn dem so ist nimm einen Level Shifter der macht das besser.
Datum:
Angehängte Dateien:schaltung ist über einen HCT125 realisiert... siehe Anhang
Datum:
Schnell genug dürften die Linedriver ja sein, aber es sind keine Levelshifter. Ich kann aus dem Schaltplan nicht erkennen mit welcher Spannung dein Prozessor arbeitet. Aber wenn er mit 5 Volt arbeitet und der HTC125 mit 3,3Volt dann gibt das sicher Probleme. Wenn dein Prozessor mit 3,3Volt arbeitet brauchst du aber nicht unbedingt den Linedriver, da die Ausgänge des Prozessor genügend Strom liefern um die SD Karte anzusteuern. Dein Schaltbild lässt darauf schliessen, dass dein Prozessor über ein Kabel an die SDKarteneinheit angeschlossen ist. Wenn das stimmt, wie lange ist das Kabel? geschirmt, ungeschirmt? Mit welcher Taktfrequenz arbeitet der Bus?
Datum:
Ach ja könnten sich die beiden SD Karten, die ja gemeinsam am Bus hängen gegenseitig beeinflussen? Soweit ich erkennen kann gibt es nur ein CS für beide SD Slots.
Datum:
Prozessor arbeitet mit 5V Das Flachbandkabel ist ungeschirmt und 8cm lang. Es sind nicht mehrere Karten gleichzeitig am Bus. Ich habe mir nur eine universal Platine gebaut, je nachdem welches SD Karten modul ich grad günstig zu kaufen bekomme. Ich kann mir nicht vorstellen, dass es an der Kommunikation liegt. Ich habe 3 Karten, bei allen funktioniert die Kommunikation "oft". Ich habe mit Karte 1 zwei Tage lang problemlos bei vollem Speed getestet. Plötzlich geht es nicht mehr, ich kann nur noch die SD Karten Information auslesen, das Datenverzeichniss ausgeben, aber ich kann kein File mehr anlegen oder in kein File schreiben. Nehme ich jetzt Karte 2 klappt alles wieder. Wenn ich Karte 1 mit meinem Computer oder meinem Fotoapperat teste geht alles. Formatieren oder medium reparieren nützt nichts. Ich kann einfach nicht mehr auf die Karte schreiben. Jedoch nach ein paar tagen pause geht die Karte wieder problemlos für die nächsten 40 Tests. Woran kann das liegen, ich mache doch nichts besonderes in meinem Code!?!?!?
Datum:
files öffnen geht auch... nur schreiben geht nicht. Das geht doch gar nicht. wie kann ich nicht schreiben können wenn alles andere funktioniert?
Datum:
Also wenn der Prozessor mit 5V arbeitet, hast du ein Problem. Die SD KArten geben 3,3Volt aus und der Prozessor kann unter umständen nicht erkennen was logisch 1 oder 0 ist.(oder umgekehrt) Ich sag dir was: Ich hatte ein ähnliches Problem. Ich hatte die Anpassung über widerstände an die SD Karten gemacht. Alles lief einwandfrei. Nur nach mehreren Stunden schreiben auf die SD Karten hatte ich plötzlich das Problem, dass die Karte nicht mehr akzeptiert wurde.(Schreibfehler) Die Karte konnte am PC auch nicht gelesen oder formatiert werden. Sie war einfach defekt. Eine andere Karte ging einwandfrei. Der Grund lag in der mangelhaften Übertragung der Signale zur Karte. Bei niedriger Übertragungsrate trat das Problem nicht auf, nur bei höherer. Dein Problem liegt meiner Meinung an der Spannungsanpassung von Karte zu Mikroprozessor. Ich denke du solltest dir einen Level shifter suchen. Ich kenn jetzt nur MAX3372E MAX3379 MAX3390 MAX3393E von meinen MkII Programmierer. Die sind aber schwer zu bekommen.
Datum:
hat jemand schon eine fertige Schaltung für so einen Level shifter? muss man nicht einen bidirektionalen Wandler nehmen, da ja daten in beide Richtungen gesendet werden? Du hast mir nur einseite aufgelistet. Informationen zu den Maxim Pegelwandlern gibts hier: http://datasheets.maxim-ic.com/en/ds/MAX3372E-MAX3393E.pdf http://www.maxim-ic.com/datasheet/index.mvp/id/3253 Danke martin
Datum:
Hier mal ein Link zu einem Fertigen KartenModul mit Pegelanpassung. http://www.shop.display3000.com/elektronikmodule/s...
Datum:
Angehängte Dateien:könnt ihr mal über das Layout drüber schauen? findet ihr Fehler? einige machen an die Kommunikationsleitungen auf der Seite der SD Karte noch 3,3V pull up Widerstände, ander wieder nicht... was meint ihr? Wie muss ich den Three-State Anschluss belegen? Danke Martin
Datum:
Ich hab so eine Pegelanpassung noch nie selbst aufgebaut, bzw benötigt. Aber soweit ich erkennen kann sind bidirektionale Shifter so aufgebaut, dass sie nur wenig Strom am Ausgang liefern, und daher von einem µC Ausgang überschrieben werden können. Das bedeutet aber auch, dass bei Batterieanwendungen ein erhöhter Stromverbrauch vorhanden ist. Es gibt aber Level Shifter in dem ein und Ausgänge vorhanden sind, die halt nur als Ein bzw Ausgang verwendet werden können.
Datum:
Soweit ich dein Schaltbild verstehe, sieht alles bis auf eines gut aus. Du solltest Three-State auf 5Volt legen. Oder schaltbar machen wenn du strom sparen willst! Jedenfall muss laut Datenblatt 5Volt anliegen wenn der Level Shifter arbeiten soll. ( ich hab die Pin zu Pin Richtigkeit deiner Schaltung nicht kontrolliert)
Datum:
Ach ja noch was: Wenn du mit dem µC erkennen willst welche Karte eingesteckt wurde solltest du die Schalter an den SD Slots getrennt abfragen. Ansonsten erkennst du immer nur einen Zustand, also Karte(n) drin. Aber das ist nur wichtig wenn du auch wirklich beide Kartenslots verwenden willst, was ja gar nicht geht weil du nur ein CS durch schaltest und keine weiteren Ports am Level Shifter frei hast. Aber würd ich mir noch vorher überlegen bevor du ein Layout machst.
Datum:
das sind zwei verschiede adapter layouts die liegen auf der platine übereinander. Ich kann daher nur eins bestücken, je nachdem welches isch zu erst zu kaufen bekommmen und welches günstiger ist
Datum:
Hi, ich beabsichtige Rolands card library auf der "OpenLog" Hardware Basis als Logger (Modellflug) einzusetzen. Das Problem ist nur, das das System irgentwann Spannungslos wird. Es ist nicht kritisch, wenn die letzte Minute nicht geloggt ist. Wie ist der Filezustand in diesem Falle wenn die Karte anschliessend in einem PC ausgelesen werden soll? Ist das File leer, oder ist es bis zum letzten geschriebenen Buffer gefüllt? Müsste man zwingend zyklisch einen "sync" durchführen oder sogar zyklisch das File schliessen und neu im append Mode öffnen? Es fallen alle 340ms 512 Byte Daten an. Gruß Ingo
Datum:
>Das Problem ist nur, das das System >irgentwann Spannungslos wird. Dann musst du die Spannung überwachen! >Es ist nicht kritisch, wenn die letzte Minute nicht geloggt ist. Wie ist >der Filezustand in diesem Falle wenn die Karte anschliessend in einem PC >ausgelesen werden soll? Ist das File leer, oder ist es bis zum letzten >geschriebenen Buffer gefüllt? Wenn du Pech hast und bei zu wenig Spannung schreibst kann die ganze Datei Schrott sein. Eventuell sogar das komplette Dateisystem auf der Karte zerstört werden. >Müsste man zwingend zyklisch einen "sync" durchführen oder sogar Kann man machen. Siehe aber auch oben. >zyklisch das File schliessen und neu im append Mode öffnen? Es fallen >alle 340ms 512 Byte Daten an. Das könnte zu lange dauern.
Datum:
> Es ist nicht kritisch, wenn die letzte Minute nicht geloggt ist. Wie ist > der Filezustand in diesem Falle wenn die Karte anschliessend in einem PC > ausgelesen werden soll? Ist das File leer, oder ist es bis zum letzten > geschriebenen Buffer gefüllt? Es fehlt einfach nur das was in den 512 Bytes 'großen' raw_block' noch gepasst hätte. Die Datei selbst ist immer ok und sogar für m$ lesbar. > Müsste man zwingend zyklisch einen "sync" durchführen oder sogar > zyklisch das File schliessen und neu im append Mode öffnen? Es fallen Das muß man nicht denn es ist ja gerade Absicht erst einmal alles zu puffern und dann in einem Rutsch diesen Sektor auf die Karte zu schreiben. > alle 340ms 512 Byte Daten an. Das müßte man ausprobieren. In meinem Fall, wo nur wenige hundert Bytes über einen langen Zeitraum geschrieben werden, mache ich zur Sicherheit immer einen sync. Freilich kostet das Performance. Hatte aber noch nie Datenverlust. > Gruß Ingo Torsten
Datum:
Hi, bei Spannungsverlust kann ich nur über die BrownOut detection arbeiten, da ich auf der super kleinen Platine nicht herumlöten will. Wenn die Datei außer dem letzten raw_block ok ist, dann ist das mehr als ich gehofft habe. Ich hatte befürchtet, das durch fehlende Einträge in der File allocation Table zu viel fehlt bzw. nicht darauf zugegriffen werden kann. Also werde ich das Projekt mal angehen, die Demo Main von Rolands card library funktioniert schon auf der "OpenLog" Platine. Gruß Ingo
Datum:
Angehängte Dateien:Hi zusammen, Im Anhang findet Ihr die neueste Version von sd-reader. Im Vergleich zur letzten Version wurden drei Fehler behoben: - Ausgabe gleicher Dateinamen bei zwei direkt aufeinander folgenden 8.3-Dateinamen. - Berechnung falscher Clusterpositionen oberhalb von 4GB. - Endlose Auflistung des Verzeichnisinhalts bei gültigem Eintrag direkt am Ende des letzten Verzeichnis-Clusters. Viel Spaß damit! Gruß, Roland
Datum:
Hi! Ich möchte mir einen Datenlogger mit SD bauen. Gibt es da irgendwelche Beschränkungen? Also wie groß darf die SD- Karte maximal sein und was für einen µC braucht man mindestens? Danke und Gruß Tobias
Datum:
Hallo, Ich konnte es noch nicht richtig zum laufen bringen. Ich bin jetzt mal Schrittweise durchgegangen und habe zwei Dinge probiert, zum einen lasse ich eine Datei erstellen und einmal lasse ich eine auf der SD-Karte befindliche Datei öffnen. Letzteres klappt nicht, es kommt zum Fehler. Das Erstellen von Dateien klappt auch nicht richtig. Schieb ich die SD-Karte zum Lesen in den PC, so wird zwar die Datei angezeigt, möchte ich sie aber öffnen, so sagt mir Windows, dass die Datei nicht existiert und ob sie erstellt werden soll. Nutze einen ATmega16L @ 8MHz und eine SanDisk 2 GB und den Code habe ich aus der beiliegenden main.c übernommen bzw. angepasst... Es geht in dem Code unten nur die grüne LED an, also sollte beim Erstellen kein Fehler auftreten?! Wenn ich die (von mir erstellte) Datei öffne (unten auskommentiert) leuchtet die rote LED, sprich ein Fehler tritt auf. Was ich noch nicht ausprobiert habe, ist, was passiert, wenn ich eine Datei erstellen lasse und sie dann öffne. Die SD-Karte formatier ich über Windows 7 und habe auch schon das Tool SDFormatter V2.0, welches auf der Homepage von Roland stand.
int main(void) { sd_raw_init(); struct partition_struct* partition = partition_open(sd_raw_read, sd_raw_read_interval, sd_raw_write, sd_raw_write_interval, 0); if (!partition) { partition = partition_open(sd_raw_read, sd_raw_read_interval, sd_raw_write, sd_raw_write_interval, -1); if (!partition) { } } struct fat_fs_struct* fs = fat_open(partition); struct fat_dir_entry_struct directory; fat_get_dir_entry_of_path(fs, "/", &directory); struct fat_dir_struct* dd = fat_open_dir(fs, &directory); struct fat_dir_entry_struct file_entry; if (!fat_create_file(dd, "Test.log", &file_entry)) { //LED_RED_ON; } else { //LED_GREEN_ON; } /* struct fat_file_struct* fd = open_file_in_dir(fs, dd, "Track.log"); if (!fd) { LED_RED_ON; } else { LED_GREEN_ON; } char* data = "abc"; uint8_t data_len = 3; if (fat_write_file(fd, (uint8_t*) data, data_len) != data_len) { LED_RED_ON; } sd_raw_sync(); */ if (!sd_raw_sync()) { LED_RED_ON; } else { LED_GREEN_ON; } delay_s(5); LED_GREEN_OFF; LED_RED_OFF; // fat_close_file(fd); fat_close_dir(dd); fat_close(fs); partition_close(partition); return 0; } |
Datum:
Hallo, habe mir die Platine nach Riegel/Radig aufgebaut und versuche nun mal mit einer SD Karte 128MB zu testen. Als Prozessor verwende ich den ATmega328p. Die Software-Version 20101010 konnte ich ohne weiteres compilieren (Studio4) und mit Burn O Mat-USBasp in den Prozessor laden. Mit einem Terminal Programm kann ich auch kommunizieren. Ergebnis: > disk manuf: 0x02 oem: TM prod: SD128 rev: 07 serial: 0x67783a65 date: 5/4 size: 120MB copy: 0 wr.pr.: 0/0 format: 0 free: 122290176/125861888 > ls DCIM/ 0 Test/ 0 > touch Myfile error creating file: Myfile > cat Test error opening Test DCIM enthält Bilder, Test enthält einen mit Editor geschriebenen kurzen Text. Was mache ich falsch oder was habe ich noch nicht kapiert?? mfG frewer
Datum:
Hallo Werner, Schau bitte mal in die FAQ auf meiner Homepage: http://www.roland-riegel.de/sd-reader/faq/#faq_writefails http://www.roland-riegel.de/sd-reader/faq/#faq_socketcdcl Gruß, Roland
Datum:
Hallo Klaus, danke für Deinen Tipp. Nun ich habe gelesen und gelesen, konnte es aber noch nicht verwerten. Bin also genau dort noch, wo ich war. Werde mich doch viel tiefer in die Materie einlassen müssen, obwohl überall geschrieben steht, dass es ganz einfach sei. Hi Roland, habe die Änderungen in die config.h eingebaut, weil ich meinen Sockel ohne die Erkennung eingebaut habe. Die Kapazitäten waren schon immer drin und die Dioden aktiviere ich mit einem 2KOhm Widerstand, so dass immer die ca 3,5V anliegen (zusätzlich mit 1µ Tantal abgeblockt). Trotzdem meldet die Eingabe > cat Test wieder "error opening Test". >touch Myfile hingegen legt jetzt offenbar einen File an, denn ich bekomme mit >ls DCIM/ 0 Test/ 0 Myfile 0 > und mit >write Myfile 'Diesen Text sollte ich in Myfile wiederfinden' bekomme ich >ls DCIM/ 0 Test/ 0 Myfile 35 > und mit >cat Myfile 00000000: 74 20 73 6f 6c 6c 74 65 't sollte' 00000008: 20 69 63 68 20 69 6e 20 ' ich in ' 00000014: 4d 79 66 69 6c 65 20 77 'Myfile w' 00000018: 69 65 64 65 72 66 69 6e 'iederfin' 00000020: 64 65 6e 65 72 66 69 6e 'denerfin' nun ein bisschen komisch aber vielleicht liegt das auch meiner Eingabe. Werde mal noch etwas experimentieren. Jedenfalls vielen Dank, es geht schon was. mfG frewer Sorry, hatte dazwischgeschrieben!!!! Nun interpretiere ich das Ergebnis, dass die Datei Test keinen Inhalt hat (0) obwohl dort drin steht "Das Wetter ist schön" (mit dem PC über einen Cardreader beschrieben). Hat das mit der Methode des Schreibens mit dem PC zu tun???
Datum:
Hi Werner, 1. Schau Dir mal die Syntax für den write-Aufruf an, Du verwendest den Befehl falsch. 2. Das mit den Dioden und dem Widerstand hab ich nicht verstanden. 3. "Test" ist doch ein Ordner, was erwartest Du denn da als Größe?? 4. Bei Interpretation der cat-Ausgabe braucht man die Dateigröße, da der Einfachkeit halber die letzte Zeile nicht entsprechend der Dateigröße abgeschnitten wird. In Deinem Beispiel sind also nur noch die Bytes 0x20 bis 0x22 gültig. Gruß, Roland
Datum:
Hallo Roland, vielen Dank für Deinen Kommentar. Mittlerweile bin ich einen Schritt weiter und verstehe auch nach detaillierter Durchsicht des "main" Deine diversen Befehle. Mit dem Widerstand zwischen der letzten Diode und Masse erzeuge ich eine kontinuierliche Vorspannung am SD-Adapter auch, wenn die Karte entnommen wird. Nicht ganz kapiere ich bis jetzt die Anzeige für die Datei Test\ mit der Angabe der Größe 0. Denn die Datei enthält, genau wie meine Datei Myfile einen kurzen Text und ist kein Directory. Warum kann ich also Myfile lesen aber Test nicht? Bin jetzt dabei, mal ein paar eigene Befehle zu schreiben. Mal gespannt wie das klappt. mfG Werner
Datum:
Hi Werner, "Test" wird als Verzeichnis interpretiert, das zeigt der Schrägstrich nach dem Namen an. Insofern ist auch klar, warum Du "Test" nicht ausgeben kannst. Kannst Du mit > cd Test in das Verzeichnis wechseln? Wenn ja, was zeigt > ls an? Gruß, Roland
Datum:
Hallo Roland,
ja, das hat funktioniert. Ich komme in das Verzeichnis Test mit cd ..
und finde dann eine Datei mit meinem Text. Um nicht dauernd die Wandlung
HEX in Zeichen händisch machen zu müssen, habe ich Deine Routine cat
geändert und bekomme nun den Text der Datei als Zeichen ausgedruckt.
Allerdings nur gewandelt, d.h. auch der alte Müll in der Datei wird
ausgedruckt. Meine Frage ist, warum wird das Endezeichen der Datei nach
der Eingabe nicht gesetzt und warum der Ausdruck nicht an diesem
Endezeichen beendet? Sowohl in cat ... als auch in "meinem" read, das ja
identisch Deinem cat .. ist.
// Eingabe read: - Datei-Inhalt als Text ausgeben
else if(strncmp_P(command, PSTR("read "), 5) == 0)
{
command += 5;
if(command[0] == '\0')
continue;
/* search file in current directory and open it */
struct fat_file_struct* fd = open_file_in_dir(fs, dd,
command);
if(!fd)
{
uart_puts_p(PSTR("error opening "));
uart_puts(command);
uart_putc('\n');
continue;
}
/* print file contents !!meine kleine Änderung!!*/
uint8_t buffer[8];
while(fat_read_file(fd, buffer, sizeof(buffer)) > 0)
{
for (i=0;i<8;i++) {uart_putc(buffer[i]);}
}
uart_putc('\n');
fat_close_file(fd);
}
///
Kann das sein, dass das '\0' im write command nicht bei jeder Eingabe
als Endekennung geschrieben wird?
mfG
Werner
Datum:
Hallo Werner,
Es gibt kein "Endezeichen" in einer Datei. Jedes Byte in einer Datei ist
gültig, somit kann es kein Byte mit einer Sonderbedeutung geben. Auch
'\0' hat keine besondere Bedeutung. Den FAT-Funktionen werden deshalb
die Daten immer als Tupel (Puffer, Länge) übergeben, und nicht nur als
(Puffer).
Mein write-Befehl schreibt die eingegebenen Zeilen nacheinander in die
Datei, ohne Trennung dazwischen (auch kein Leerzeichen, es sei denn man
gibt es explizit ein). Wenn Du da Null-Bytes oder was auch immer
dazwischen haben willst, musst Du die write-Implementierung eben
entsprechend abändern.
Dass "alter Müll" in der Datei steht, liegt daran, dass die Datei nicht
gekürzt wird. Wenn Du z.B.
> write test.txt 25
sagst, wird der Dateiinhalt ab Byte-Offset 25 mit den von Dir
eingegebenen Zeichen überschrieben, bzw. an die Datei angehängt. Wenn Du
aber weniger Zeichen eingibst als die Datei bereits lang ist, bleiben
die alten (nicht überschriebenen) Daten eben bestehen. Auch das kannst
Du natürlich ändern (fat_resize_file()).
Denk bitte auch daran, dass der Puffer für die Kommandozeile nur 24
Zeichen lang ist und beim Erreichen der Maximallänge implizit ein Enter
angenommen wird.
Viele Grüße,
Roland
Datum:
merci Roland, ich glaube, dass ich die Syntax jetzt verstanden habe. Mit meinem \0 dachte ich an das Ende eines STRING und diesen Wert wollte ich zum Begrenzen der Ausgabe benutzen. Wenn ich das write Kommando richtig verstehe, dann wird auch \0 abgefragt und in die Datei geschrieben. D.h. ich kann in meinem Read Kommando die "Endeabfrage" implementieren ohne das write Kommando anzutasten. Jetzt verstehe ich auch, warum immer wieder bei der Eingabe das < Zeichen kam. Hatte mich schon gewundert. Aber dem Grunde nach verändert das ja nicht den Inhalt in der datei. Summa summarum läuft es mit meinem kleinen ATmega328p und der Karte richtig prima. Wenn ich noch was vertrauter bin, dann kann ich damit "durchstarten". Z.Zt. bin ich dabei, die Routinen zu verstehen - was schon ganz schön schwierig ist (bin halt älteres Semester) - aber ich komme langsam voran. Nochmals Dank und bis zur nächsten Frage mfG Werner
Datum:
Hi Roland, habe noch ein Versuchsergebnis mit dem ich noch nicht umgehen kann. Ich habe folgende Baum auf der SD-Karte: DCIM/ Test/ Myfile Ich gehe mit cd Test in ein das Directory Test und beschreibe dort zB einen File. Jetzt möchte ich in das Directory DCIM/ mit zB cd DCIM oder cd /DCIM. Wäre schön geht aber nicht. Auch komme ich nicht in das Root Dir außer natürlich mit "init". Gibt es da eine Hilfestellung? Grüße vom Rhein nach ?? Werner
Datum:
Hallo Werner, In der Beispiel-Shell der main.c beziehen sich die meisten Operationen auf das aktuelle Verzeichnis. FAT stellt für jedes Verzeichnis die Spezialnamen "." und ".." bereit. Dabei steht "." für das aktuelle Verzeichnis und ".." für das übergeordnete Verzeichnis. Dein Ziel erreichst Du also so: > cd Test > ls ... > cd .. > cd DCIM > ls ... Denk bitte dran, das ist ein ganz primitiver Prompt, mit relativen Pfaden und dergleichen kann der nichts anfangen (wenngleich man das natürlich programmieren könnte). Viele Grüße, Roland
Datum:
Hallo Roland, bei aller Liebe, die Variante der Eingabe konnte ich Deiner Beschreibung nicht entnehmen. Aber man lernt ja nicht aus. Es klappt prima so. Nun, das ganze ist ja mehr zum Lernen als zum Anwenden gedacht. Meine Absicht ist eh nur einfache Datenspeicherung. Aber Deine Programmsystem hat mich gleich fasziniert, weil es für mich sehr professionell aussieht und mich beim Durcharbeiten immer wieder überrascht, weil ich die gegenseitigen Links immer suche und außer den eindeutigen Zuordnungen FAT_, Partition_,sd_raw usw immer lange suche, bis ich den "Link" finde. Aber es macht viel Spaß. Danke für die rasche Hilfe und Grüße von der Hochwasser-Front Werner
Datum:
Angehängte Dateien:Hallo alle miteinander, Als kleines Update zwischendurch gibts eine neue sd-reader-Ausgabe. Die wichtigsten Änderungen: - Umbenennung bzw. Verschieben von Dateien und Verzeichnissen. - Korrekturen bei der Behandlung von Little-Endian-Integern auf 16- und 32-Bit-Architekturen. - Zusätzlichen Rückgabewert für fat_create_file(), um bereits existierende Dateien zu erkennen. - Doku zum Auslesen der aktuellen Dateiposition mittels fat_seek_file(). Wie immer findet Ihr das Update im Anhang oder unter http://www.roland-riegel.de/sd-reader/ Gruß, Roland
Datum:
Hallo, für ein Projekt benötige ich die folgenden Funktionen. - get Anzahl der Zeilen in einem file - get Zeile, Nummer ... aus dem file zurück Hat schon jemand solch eine Funktion geschrieben und würde diese mir zur verfügung stellen? Vielen Dank martin
Datum:
eine kleine Frage, kann man die SD-Karte an beliebigen Ports anschließen oder muß es immer Hardware-MOSI/MISO/SCK sein?
Datum:
vom Programm wird nur der Hardware SPI unterstützt... Software SPI wäre aber auch möglich, muss du dann nur selber implementieren.
Datum:
danke für die info - schade, da wüßte ich jetzt nicht wie das gehen sollte.
Datum:
So ich hab jetzt mal einen ersten entwurf meiner getLine funktion geschrieben. Die funktion läuft. Hat jemand vielleicht noch eine Idee wie man die Funktion schneller und effektiver gestalten kann. Vielleicht könnte man auch einen Zeielen Abschnitt sich zurückgeben lassen... also von Zeile x bis Zeile y. Ich hoffe es haben einige Interesse.
//########################################################################################## uint8_t file_getLine(uint16_t lineNr,char* zielbuffer)// anzahl Zeilen aktuelles file { // Rückgabe der Zeilenlänge // maximale Zeilenlänge von 40 Zeichen if(fd) { if (lineNr < 1 ) {return 0;} uint16_t counterLines =0; int32_t pos_after_last_enter = 0; uint8_t arbeitsbuffer[40]; uint8_t count; //########## Anfang der n-ten Zeile suchen und position in "pos_after_last_enter" zurückgeben //########## es werden alle '\n' gezählt bis die Anfangsposition der gesuchten Zeile gefunden ist while(counterLines < lineNr-1) { if(!fat_seek_file(fd, &pos_after_last_enter, FAT_SEEK_SET)) {/* error*/} count = fat_read_file(fd, arbeitsbuffer, 40); for(intptr_t i = 0; i < count; ++i) { if(arbeitsbuffer[i] == '\n') { counterLines++; pos_after_last_enter+=i+1;// Zeiger auf Zeichen nach dem letzten Enter break; } } } //########## Daten ab der gefundenen Position auslesen und in Zielbuffer schreiben if(!fat_seek_file(fd, &pos_after_last_enter, FAT_SEEK_SET)) {/* error*/} count = fat_read_file(fd, arbeitsbuffer, 40); for(intptr_t i=0; i<count; ++i) { zielbuffer[i] = arbeitsbuffer[i]; if(arbeitsbuffer[i] == '\n') { zielbuffer[i+1] = 0; return i; // return Zeilenlänge } } } return 0; } |
Datum:
Zu erst möchte Ich “danke schon” sagen. Ihr Project hilft mir wirklich schnell voran. Aber dann habe ich noch eine frage; Moderne AVR können sich selbst programmieren. Wäre es möglich einen AVR aus eine Datei zu laden? Sagen wir mal das wenn es auf eine SD-Karte eine Datei namens „imageXXX.avr“ gibt diese geladen wird falls der Nummer XXX größer ist als die heutige Versionsnummer. Oder müsste man eine .hex Datei laden können? Verzeihung für mein Deutsch, aber ich nehme an man versteht wo die Gedanken gehen.
Datum:
Hallo Roland, erstmal ein großes danke schön für die Bibliohek. Nach einigen Startschwierigkeiten bin ich nun doch in der Lage, damit Dateien zu lesen, anzulegen und zu schreiben. Allerdings möchte ich mit der Bibliothek MP3's auslesen und zu einem Decoder schicken. Hier gibt es aber Probleme. Habe zum Testen nun eine .txt angelegt mit 64 Zeichen Inhalt. Die ersten 32 werden auch korrekt in den Buffer gelesen, das wars dann aber auch. Das Programm durchläuft einmal die Schleife und springt dann raus, obwohl noch 32 neue Bytes darauf warten, gelesen zu werden.
void play_sound(const char *file_name, struct fat_fs_struct* fs, struct fat_dir_struct* dd) { int32_t bytesRead = 0; int32_t totalBytesRead = 0; int countVar; uint8_t songbuffer[32]; struct fat_file_struct* fd; fd = open_file_in_dir(fs, dd, file_name); bytesRead = fat_read_file(fd, songbuffer, 32); while(bytesRead > 0) { totalBytesRead+=bytesRead; fat_close_file(fd); unselect_card(); // hier steht ein Routine zum senden des Buffer-Inhaltes an den Decoder ... // select_card(); fd = open_file_in_dir(fs, dd, file_name); fat_seek_file(fd,&totalBytesRead,FAT_SEEK_SET); bytesRead = fat_read_file(fd, songbuffer, 32); } fat_close_file(fd); } |
Hoffe, mir kann geholfen werden. Gruß Steffen
Datum:
Hallo Steffen, Mal davon abgesehen, dass das so fürchterlich ineffizient ist, sollte es schon funktionieren. Könntest Du bitte zuerst mal sicherstellen, dass alle Funktionsaufrufe Erfolg zurückmelden? Was passiert, wenn die Datei 32 Bytes länger ist? Wird dann die Schleife einmal mehr durchlaufen? Was macht eigentlich das select_card()/unselect_card() in der Schleife? Gruß, Roland
Datum:
Hallo Roland! Danke für die Antwort. Hatte ich vergessen mit reinzuschreiben, der Decoder hängt auch am SPI, daher muss ich die MMC vor jedem neuen Leseaufruf neu anwählen bzw. bevor ich die Daten zum Decoder schicke abwählen. Und ja, wenn mehr als 32 Bytes zu lesen sind, soll die Schleife nochmal durchlaufen werden. Wie würde denn eine effizientere Variante aussehen? Bin für Hinweise etc. offen. :) Gruß Steffen
Datum:
Mal ein kleines Update: Ohne SPI-Übertragung an den Decoder wird die Datei jetzt ordentlich ausgelesen. Wenn ich allerdings die Übertragung wieder mit reinnehme, wird mir im zweiten Schleifendurchlauf beim Aufruf von fat_read_file eine -1 zurückgegeben. Laut Debugger wird der Fehler direkt bei der Parameterüberprüfung in fat_read_file ausgegeben. Kann mir das nicht erklären, ich verändere weder fd, noch den songbuffer noch die Bufferlänge. Gruß Steffen
Datum:
Scheinbar geht die Information für fd verloren, obwohl der es über open_file_in_dir nach dem Übertragen an den Decoder wieder geladen wird. Jedenfalls gibt er bei der Parameterüberprüfung von fd in fat_read_file -1 zurück.
Datum:
Hallo Roland, hab das Problem gelöst gekriegt. Manchmal hilft es, wenn man sich nochmal alle Pin-Deklaration anguckt. Du meintest, dass meine Variante sehr ineffizient ist. Das macht sich auch akustisch bemerkbar. Wie würde Deiner Meinung nach eine effizientere Funktion aussehen? Gruß Steffen
Datum:
>Du meintest, dass meine Variante sehr ineffizient ist. Das macht sich >auch akustisch bemerkbar. Wie würde Deiner Meinung nach eine >effizientere Funktion aussehen? So vieleicht? Datei offen halten bis der Song fertig ist.
void play_sound(const char *file_name, struct fat_fs_struct* fs, struct fat_dir_struct* dd) { int32_t bytesRead = 0; int countVar; uint8_t songbuffer[32]; struct fat_file_struct* fd; fd = open_file_in_dir(fs, dd, file_name); if(fd) { do { bytesRead = fat_read_file(fd, songbuffer, 32); // hier steht ein Routine zum senden des Buffer-Inhaltes an den Decoder ... // } while(bytesRead > 0) fat_close_file(fd); } } |
Datum:
Nachtrag: kleine Verbesserung;)
void play_sound(const char *file_name, struct fat_fs_struct* fs, struct fat_dir_struct* dd) { int32_t bytesRead = 0; int countVar; uint8_t songbuffer[32]; struct fat_file_struct* fd; fd = open_file_in_dir(fs, dd, file_name); if(fd) { do { bytesRead = fat_read_file(fd, songbuffer, 32); if(bytesRead > 0) { // hier steht ein Routine zum senden des Buffer-Inhaltes an den Decoder ... // } } while(bytesRead > 0) fat_close_file(fd); } } |
Datum:
Hallo Steffen, So wie Holger geschrieben hat, sollte es schon wesentlich besser funktionieren. Es ist einfach nicht notwendig, die Datei ständig zu schließen, wieder zu öffnen und die Leseposition neu zu setzen. Das sind alles Operationen, die relativ aufwendig sind. Je nachdem, wieviel RAM Du noch frei hast, sollte der Puffer zum Lesen der Daten auch noch wesentlich vergrößert werden. Das ist im Vergleich zu den Dateioperationen aber nicht mehr ganz so wichtig. Gruß, Roland
Datum:
Hallo zusammen! An der Stelle wollte ich mich einfach nochmal für die schnelle Hilfe bedanken, die mir zuteil wurde. :) Gruß Steffen
Datum:
Hallo Roland, ich möchte Daten (Texte) mit einem ATmega2560 auf eine SD-Card schreiben, die dann später am PC ausgelesen werden sollen. Deine Daten (Version 20110243) habe ich übernommen. Da an meiner MCU ein LCD und einige Taster sind, benötige ich "alles" mit "uart" nicht. Meldungen gehen ans LCD. Nun das Problem: "sd_raw_init" und "Partition_open" wird ausgeführt, aber dann kommt die Meldung "opening filesystem failed". Ich vermute, dass die Hardware OK ist, da "...init" und "...open" durchlaufen werden. Wieso es aber bei "fs_open" nicht geht weis ich (noch) nicht. Über Infos würde ich mich freuen. Vielen Dank! MfG Daniel








