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
@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.
@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 :)
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.
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.
@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?
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.
@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 ?
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.
@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.
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...
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.
@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
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.
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? :)
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.
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
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
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
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
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.
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
Ach so, zur MCU. Ja klar, ein ATmega16 ist ok. Mit dem kannst Du aber
nicht meine Platine nutzen. Für die brauchst Du einen ATmega8 oder
pinkompatiblen, also einen von ATmega8/48/88/168.
Roland
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
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
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
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
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
@ 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
@ 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
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
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
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
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
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
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
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.
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
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
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
@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.
@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
@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
@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
@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
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
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
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.
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
>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
@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.
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
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.
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
>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?
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.
@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
>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.
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
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
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
@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
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
@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
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
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
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
@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
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
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
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.
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.
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
@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
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
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
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
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
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
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
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
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
> - 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
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
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
> 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
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
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
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
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
> 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
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
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
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
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
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
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
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
@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
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
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
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
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
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
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
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
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
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
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
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
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
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 ...
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
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
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
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
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
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
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 ?
> 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
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
@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
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
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.
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
@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
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.
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.
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
Hi,
hat jemand schon Verzeichnisse angelegt? Ich kriege es nicht richtig hin
und habe immer alten Datenmüll in den Verzeichnissen.
Danke!!!
Gruß
Holger
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
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
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
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.
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
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...
@ 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
@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
@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
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 :-)
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?
@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
@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.
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
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.
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
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.
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
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
@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
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.
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
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.
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
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
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
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
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
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
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
@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
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
@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
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
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
@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
@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
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ß.
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
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
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
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
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
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
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
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
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
@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
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:
1
#elif defined(__AVR_ATmega64__) || \
2
defined(__AVR_ATmega128__)
3
/* Attention: all pins must be defined for correct work */
4
#define configure_pin_mosi() DDRB |= (1 << PB2)
5
#define configure_pin_sck() DDRB |= (1 << PB1)
6
#define configure_pin_ss() DDRB |= (1 << PB0)
7
#define configure_pin_miso() DDRB &= ~(1 << PB3)
8
9
#define select_card() *pSPI_CS &= ~(1 << SPIP4)
10
#define unselect_card() *pSPI_CS |= (1 << SPIP4)
11
#else
Zu JTAG kann ich leider nichts sagen ich benutze nur den ISP Anschluss.
Tschau
Michael
@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
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
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
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
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
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
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
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.
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
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!
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
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
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
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
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
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...
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
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
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!
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
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
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
hallo,
ich hab grad laut anleitung von ulrich radigs webseite ein
brotbrett bestueckt.
http://www.ulrichradig.de/site/atmel/avr_mmcsd/gfx/MMCSDSCH.JPG
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
@ 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 :(
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
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
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
> 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
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
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.
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
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
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
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)
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 ;)
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
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
> 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
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.
> 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
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
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:
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
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?
@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
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).
> ..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:
1
/* set block size to 512 bytes */
2
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
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.
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
>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.
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?
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?
>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.
>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!
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
1
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
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 ?
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.
@ 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
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
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??
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
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
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:
1
intmain()
2
{...
3
/* print some card information as a boot message */
4
print_disk_info(fs);
5
...}
Versuch:
1
voidtest(void);
2
intmain()
3
{...
4
/* print some card information as a boot message */
5
//print_disk_info(fs);
6
test();
7
...}
8
9
voidtest()
10
{
11
print_disk_info(fs);
12
}
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
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
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
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
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
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
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
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.
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
> 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
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
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.
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
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
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 ...
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:
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:>
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
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
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
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
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
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
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
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:
1
manuf: 0x06
2
oem: RK
3
prod: SD
4
rev: 00
5
serial: 0x000004b1
6
date: 12/5
7
size: 127139840
8
copy: 0
9
wr.pr.: 0/0
10
format: 0
11
free: 126644224/126693376
12
1: success1
13
2: success2
14
3: success3
15
4: success4
16
5: success5
17
6: success6
18
7: success7
19
8: success8
20
9: success9
Linux zeigt dann an:
1
drwxr-xr-x 2 root root 16K 1970-01-01 01:00 ./
2
drwxr-xr-x 24 root root 4,0K 2007-10-15 09:04 ../
3
-rwxr-xr-x 1 root root 0 1980-01-01 01:00 1*
4
-rwxr-xr-x 1 root root 0 1980-01-01 01:00 2*
5
-rwxr-xr-x 1 root root 0 1980-01-01 01:00 3*
6
-rwxr-xr-x 1 root root 0 1980-01-01 01:00 4*
7
-rwxr-xr-x 1 root root 0 1980-01-01 01:00 5*
8
-rwxr-xr-x 1 root root 0 1980-01-01 01:00 6*
9
-rwxr-xr-x 1 root root 0 1980-01-01 01:00 7*
10
-rwxr-xr-x 1 root root 0 1980-01-01 01:00 8*
11
-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:
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
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
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:
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
@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
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
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
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:
1
void sd_raw_send_byte(uint8_t b)
2
{
3
while ( !(UCSR0A & (1<<UDRE0)) );
4
UDR0 = b;
5
}
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:
1
void sd_raw_send_byte(uint8_t b)
2
{
3
while ( !(UCSR0A & (1<<UDRE0)) );
4
UDR0 = b;
5
while ( !(UCSR0A & (1<<RXC0)) );
6
b = UDR0;
7
}
Mit diesen zwei zusätzlichen Zeilen läuft jetzt alles einwandfrei!
Herzlichen Dank für Deine Unterstützung und viele Grüße!
Martin
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
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
@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
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
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
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
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
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
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:
1
> manuf: 0x1b
2
oem: SM
3
prod: SMI
4
rev: 10
5
serial: 0x099da84f
6
date: 7/7
7
size: 1017643008
8
copy: 0
9
wr.pr.: 0/0
10
format: 0
11
free: 1016758272/1017249792
12
> ls
13
abc/ 0
14
file.txt 16
15
a/ 0
16
>
17
> cat file.txt
ab hier hängt's. Ein weiteres Beispiel, wenn der File in einem
Unterverzeichnis ist:
1
manuf: 0x1b
2
oem: SM
3
prod: SMI
4
rev: 10
5
serial: 0x099da84f
6
date: 7/7
7
size: 1017643008
8
copy: 0
9
wr.pr.: 0/0
10
format: 0
11
free: 1016758272/1017249792
12
> cd abc
13
>
14
> ls
15
./ 0
16
../ 0
17
abc.txt 24
18
>
19
> cat abc.txt
20
manuf: 0x1b
21
oem: SM
22
prod: SMI
23
rev: 10
24
serial: 0x099da84f
25
date: 7/7
26
size: 1017643008
27
copy: 0
28
wr.pr.: 0/0
29
format: 0
30
free: 1016758272/1017249792
31
>
Hier springt das Programm an den Anfang.
Ich hoffe, dass der Fehler jetzt klarer beschrieben ist und ihr helfen
könnt.
Gruss Reinhard
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
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
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
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
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
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?
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
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
@ Reinhard
Habe jetzt mal Dein Image auf meine Karte gespielt:
1
manuf: 0x06
2
oem: RK
3
prod: SD
4
rev: 00
5
serial: 0x000004b1
6
date: 12/5
7
size: 127139840
8
copy: 0
9
wr.pr.: 0/0
10
format: 0
11
free: 1016758272/1017249792
12
> ls
13
abc/ 0
14
file.txt 16
15
a/ 0
16
> cat file.txt
17
00000000: 61 62 63 64 65 66 67 0a
18
00000008: 31 32 33 34 35 36 37 0a
19
> cd abc
20
> ls
21
./ 0
22
../ 0
23
abc.txt 24
24
> cat abc.txt
25
00000000: 31 32 33 34 35 36 37 38
26
00000008: 39 30 0a 61 62 63 64 65
27
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
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:
1
manuf:0x1b
2
oem:SM
3
prod:SMI
4
rev:10
5
serial:0x099da84f
6
date:7/7
7
size:1017643008
8
copy:0
9
wr.pr.:0/0
10
format:0
11
free:1016709120/1017249792
12
>cat2.txt
13
00000000:200a020000000000
14
>write2.txt0
15
<jetztfunkt's
16
<dankeanRoland
17
<
18
>cat2.txt
19
00000000:6a65747a74206675
20
00000008:6e6b74277364616e
21
00000010:6b6520616e20526f
22
00000018:6c616e646e20526f
23
>
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
>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 !
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
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
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
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
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
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
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
@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
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
@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
@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
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.
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.
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
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
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
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
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
@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
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
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
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
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
@ 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
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
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
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
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
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
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
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:
1
structfat16_dir_struct*dir=0;
2
3
while(1)
4
{
5
if(Taster_Enter_pos_F)
6
{
7
structfat16_dir_entry_structfile_entry;
8
fat16_create_file(dir,"test.kml",&file_entry);
9
sd_raw_sync();
10
}
11
}
Ich danke dir für deine Hilfe, wirklich klasse Support.
Gruss
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
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:
1
manuf:0x01
2
oem:PA
3
prod:S008B
4
rev:41
5
serial:0x39d181e1
6
date:9/3
7
size:6799360
8
copy:0
9
wr.pr.:0/0
10
format:0
11
free:6725632/6760448
Könnte das Problem nur an der geringen Größe der Karte liegen?
Gruß
Markus
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
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
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
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?
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
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
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
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
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
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.
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
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
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__fat16__file.html
for the documentation of the FAT16 file handling.
Greetings,
Roland
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
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
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
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
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
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
@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?
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
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
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
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
@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
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.
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?
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.
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.
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
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
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
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
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
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
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
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
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.
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
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.
Bin jetzt doch noch einen Schritt weiter gekommen.
Nach Durchstöbern der ganzen Config-Files habe ich
1
#define FAT_FAT32_SUPPORT SD_RAW_SDHC
in
1
#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.
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
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
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)
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.
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
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
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
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
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:
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.
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
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
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.
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
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.
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
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:
1
if(!partition)
2
{
3
/* If the partition did not open, assume the storage device
4
* is a "superfloppy", i.e. has no MBR.
5
*/
6
partition=partition_open(sd_raw_read,
7
sd_raw_read_interval,
8
sd_raw_write,
9
sd_raw_write_interval,
10
-1
11
);
12
if(!partition)
13
{
14
#if DEBUG
15
uart_puts_p(PSTR("opening partition failed\n"));
16
#endif
17
continue;
18
}
19
}
Hat irgendjemand etwas ähnliches beobachtet und kann mir vieleicht einen
Tip geben? Ich kann es mir nicht erklären, was da genau passiert.
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
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
Hi,
wollte nochmal Feedback geben, dass die unerklärlichen Abstürze mit
- AVR-Studio 4.14.589
nicht auftreten. Dafür ist das Debuggen nicht so komfortabel, weil
AVR-Studio nicht automatisch die Breakpoints anspringt. Naja, irgendwas
ist ja immer.
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:
1
globalvoidvSD_Init(void)
2
{
3
uint8buffer[24];
4
5
if(sd_raw_init()==TRUE)
6
{
7
vLCD_Control(ZEILE_1,"SD-Card found");
8
9
// open first partition
10
structpartition_struct*partition=partition_open(
11
sd_raw_read,
12
sd_raw_read_interval,
13
/*sd_raw_write*/0,
14
/*sd_raw_write_interval*/0,
15
0
16
);
17
18
if(partition==FALSE)
19
{
20
/* If the partition did not open, assume the storage device
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?
Hallo Marcel,
Ich finde Deinen Code mit den ganzen verschachtelten ifs etwas
unübersichtlich. Mach es lieber so:
1
if(!partition)
2
{
3
/* lcd error message */
4
return;
5
}
6
7
/* ... */
8
9
if(!fs)
10
{
11
/* output lcd error message */
12
return;
13
}
14
15
/* 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
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
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
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
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 ;-)
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
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.
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
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
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!
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
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
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.
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)?
1
>while(fat_read_dir(dd,&directory))
2
>{
3
>if(strcmp(directory.long_name,"test.txt")==0)
4
>{
5
>
6
>strcpy(test,directory.long_name);
7
>
8
>uart_puts(test);
9
>break;
10
>}
11
>
12
>}
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?
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
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
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
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!
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.
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:
1
#if !SD_RAW_SAVE_RAM
2
/* the first block is likely to be accessed first, so precache it here */
3
raw_block_address=(offset_t)-1;
4
#if SD_RAW_WRITE_BUFFERING
5
raw_block_written=1;
6
#endif
7
if(!sd_raw_read(0,raw_block,sizeof(raw_block)))
8
return0;
9
#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:
1
/* wait for data block (start byte 0xfe) */
2
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.
Hallo Simon,
Simon K. wrote:
> Eine Anmerkung und eine Frage:>
1
>voidsd_raw_send_byte(uint8_tb)
2
>{
3
>SPDR=b;
4
>/* wait for byte to be shifted out */
5
>while(!(SPSR&(1<<SPIF)));
6
>SPSR&=~(1<<SPIF);
7
>}
8
>
>> 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:
1
>/* wait for data block (start byte 0xfe) */
2
>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
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.
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
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
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.
@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
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:
1
if(!partition)
2
{
3
/* If the partition did not open, assume the storage device
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
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
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?
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
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
@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
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
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
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.
@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
Hallo
ich möchte diesen Thread nicht verwässen und habe deshalb einen neuen
Thread gestartet.
Wie sieht es mit der Lebensdauer der Karte aus, wenn man pro Sekeunde
kleine Einheiten schreibt?
Ist das unsinnig?
Wie sollte man da vorgehen?
MfG
Achim
siehe ==>Beitrag "SD Card GPS Logger optimieren?"
Hallo 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
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
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
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
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 :)
@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
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:
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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...
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...
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
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
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.
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
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
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?
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....
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.
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.
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?
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
Hallo Roland,
das Programm bleibt dann einfach hängen.
Das passiert in der Funktion
1
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
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
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
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
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
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
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
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
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
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 :-)
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
@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
@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
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
Hallo Roland,
hab´s schon ein paar mal formatiert ... vielleicht liegts am fat32 muss
das am wochenende mal ordentlich durchprobieren.
Viele Grüße
Hannes
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
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.
@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.
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.
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
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.
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?
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.
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!?!?!?
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 MAX3379MAX3390MAX3393E von meinen MkII
Programmierer.
Die sind aber schwer zu bekommen.
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
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.
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)
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.
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
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
>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.
> 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
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
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
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
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.
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
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???
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
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
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
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
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
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
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
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
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
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
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
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.
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.
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.
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
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
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
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.
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
>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.
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
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
Alex K. schrieb:> Martin Wende schrieb:>> Im 8.3 Format muss der Dateiname komplett aus Großbuchstaben bestehen.>> Sonst zickt win wenns auf der SD Karte liegt.> Juhu, das wars.... !!!> DANKE!!!!!!!!>> Meine Einstellungen sind nun:>> #define FAT_LFN_SUPPORT 0> #define FAT_DELAY_DIRENTRY_UPDATE 0> #define SD_RAW_SDHC 0> #define SD_RAW_WRITE_BUFFERING 1>> und ein sd_raw_sync(); nach jedem schreiben.>> Danke euch, ihr habt meinen Tag gerettet...
Also ich habe das gleiche Problem. Es werden zwar Dateien auf der
SD-Karte erzeugt (microSD mit 2 GB, FAT16, kein SDHC), aber die sind
leer. Ich habe die gleichen Optionen eingestellt und nur Großbuchstaben
benutzt. Leider keine Änderungen. Wenn ich chkdsk /F durchlaufen lassen,
bekomme ich die Meldung, dass "verlorene Ketten" gefunden wurden. Wenn
chkdsk diese Dateien wiederherstellt, kann ich mir den Inhalt der
Dateien im Ordner "FOUND.000" anzeigen lassen. Mein Code sieht so aus:
Probier mal sd_raw_sync() nach write/close damit die buffer vom ram auch
auf die Karte geschrieben werden bevor Du diese entfernst oder den Saft
abdrehst.
Bis zum öffnen des root Verzeichnisses klappt es, dann bekomme ich die
Fehlermeldung "failed to create file". Wäre super wenn hier jemand einen
Tipp hätte!
Viele Grüße,
Martin
Die Funktion fat_create_file() erwartet doch einen Zeiger auf die
fat_dir_entry_struct Struktur und keinen Zeiger auf einen Zeiger.
Müsste es nicht wie folgt anfangen (vor fd kein Stern)?
Hi !
Ich habe ein Problem mit dem Timing beim Öffnen einer Datei.
Und zwar liest mein Programm WAV-Dateien von der SD und gibt diese über
den PWM des Atmega168 wieder. Die Daten werden gepuffert.
Die Dateien werden per Dateiname ausgewählt.
Nur habe ich, wenn ich die Datei wechseln will, eine unschöne Pause
zwischen den Tracks.
sound_file=open_file_in_dir(fs, dd, dateiname);
Dauert verhältnismäßig lange.
Ziel des Programms soll sein, eine Schaltung mit Lagesensor und Tastern,
die jeh nach Lage oder Tastendruck einen Sound wiedergibt.
z.B. Modellbau-Schiff: Motor an, Motor läuft schnell, Motor läuft
langsam, Hupe, Motor aus usw.
Hat jemand eine Idee, wie ich ohne nennenswerte Zeitverzögerung die
Dateien hintereinander abspielen kann?
Servus,
an dieser Stelle möchte ich mich bei Roland Riegel bedanken.
Die Sourcen arbeiten einwandfrei.
Egal, ob MMC, SD, 32GB oder 2GB.
Gut gemacht. Ich hatte mir eine zeitlang überlegt, auf FatFs von ELM
umzusteigen, aber das braucht es nicht.
Gruß Klaus