Forum: Projekte & Code MMC/SD-Karte mit FAT16 an AVR


von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

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

von Senf (Gast)


Lesenswert?

Igitt was haben denn deine *.c fürne komische formatierung.
Schade, nix mit Editor anschaun, törnt mich grad ab das reinzuziehen.

von André K. (freakazoid)


Lesenswert?

@Senf:
Sieht bei mir okay aus. Deine Wortwahl und Schreibstil lassen eher
vermuten, daß Kiffen doch gesundheitsschädlich ist ;)

von Roland R. (roland) Benutzerseite


Lesenswert?

@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.

von SuperUser (Gast)


Lesenswert?

@Roland
Da du ja ohne FAT-Buffer etc. arbeitest, interessiert mich die
Geschwindigkeit die du erreichst. Hast du schon mal was gemessen?

von Roland R. (roland) Benutzerseite


Lesenswert?

@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 :)

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

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.

von Fabian (Gast)


Lesenswert?

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.

von Roland R. (roland) Benutzerseite


Lesenswert?

@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?

von The E. (the_engineer)


Lesenswert?

*abo

von Lupin (Gast)


Lesenswert?

die 3.3v stromversorgung hast du ja ganz elegant gelöst :)

von Roland R. (roland) Benutzerseite


Lesenswert?

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.

von Fabian (Gast)


Lesenswert?

@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 ?

von Roland R. (roland) Benutzerseite


Lesenswert?

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.

von Lupin (Gast)


Lesenswert?

MMC karten unterstützen bis zu 20 Mhz SPI takt. steht auch in den
datenblättern.

von Gast (Gast)


Lesenswert?

SD-Karten bis 25 MHz.

von Pete (Gast)


Lesenswert?

@roland
Wo hast Du denn den Kartenslot her ?

von Roland R. (roland) Benutzerseite


Lesenswert?

@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.

von Lupin (Gast)


Lesenswert?

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...

von Roland R. (roland) Benutzerseite


Lesenswert?

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.

von m@u (Gast)


Lesenswert?

@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

von Roland R. (roland) Benutzerseite


Lesenswert?

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.

von Lupin (Gast)


Lesenswert?

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? :)

von Fly (Gast)


Lesenswert?

Na wahrscheindlich geht ihm das RAM aus.... leider immer das selbe,
irgendeinmal trifft man auf die Grenze der AVRchen.

von Roland R. (roland) Benutzerseite


Lesenswert?

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.

von Tobias G. (tobster)


Lesenswert?

*abo

von Peter Baumann (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

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

von Gernot F. (gernotfrisch)


Lesenswert?

Kann ich damit schnell an das Ende einer Datei springen. Ich möchte MP3
tags auslesen, und die stehen am Ende der Datei (und die haben 200MB)

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Gernot F. (gernotfrisch)


Lesenswert?

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.

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Malte I. (maltomat)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Malte I. (maltomat)


Lesenswert?

Hallo Roland,

ok, alles klar, ich hatte die alte Version.

Danke
Malte

von Malte I. (maltomat)


Lesenswert?

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

von T.S. (Gast)


Lesenswert?

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

von T.S. (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

@ 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

von Malte I. (maltomat)


Lesenswert?

@ 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

von Malte I. (maltomat)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

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

von Malte I. (maltomat)


Lesenswert?

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

von Malte I. (maltomat)


Angehängte Dateien:

Lesenswert?

...hier der Schaltplan. Ich habe keien Eagle-Vorlage für den Mega32, der
Mega163 hat aber die gleiche Belegung.

von Malte I. (maltomat)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Malte I. (maltomat)


Lesenswert?

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

von neuer (Gast)


Lesenswert?

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.

von Avr N. (avrnix) Benutzerseite


Lesenswert?

abo

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Dirk Schlage (Gast)


Lesenswert?

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

von Malte I. (maltomat)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

@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.

von Roland R. (roland) Benutzerseite


Lesenswert?

@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

von Dirk Schlage (Gast)


Lesenswert?

@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

von Malte I. (maltomat)


Lesenswert?

@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

von Der T. (Gast)


Lesenswert?

Einfach Geil! :-D

abo

von Roland R. (roland) Benutzerseite


Lesenswert?

@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

von Malte I. (maltomat)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Wolfram (Gast)


Lesenswert?

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.

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Ssss S. (sssssss)


Lesenswert?

>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

von Wolfram (Gast)


Lesenswert?

@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.

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Wolfram (Gast)


Lesenswert?

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.

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Wolfram (Gast)


Lesenswert?

>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?

von Roland R. (roland) Benutzerseite


Lesenswert?

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.

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

@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

von Wolfram (Gast)


Lesenswert?

>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.

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Wolfram (Gast)


Lesenswert?


von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Uwe (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

@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

von Wirus! (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

@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

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

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

von Malte I. (maltomat)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Simon K. (simon) Benutzerseite


Lesenswert?

die kann man auch hier hochladen. Ihr immer mit eurem Email
hinundhergeschickte. Dafür ist das Forum nicht da!

von Roland R. (roland) Benutzerseite


Lesenswert?

@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

von Malte I. (maltomat)


Lesenswert?

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

von T.S. (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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.

von Peter bb (Gast)


Lesenswert?

Welche aufgabe übernimmt eigentlich am avr immer der port ss an der
mmc-karte? kann man auch eien anderen port nehmen?

von Roland R. (roland) Benutzerseite


Lesenswert?

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.

von Peter bb (Gast)


Lesenswert?

da ich nur die mmc-karte anschliessen möchte und diese auch nur
betreibe, kann man den anschluss an der mmc cs sofort auf masse legen?

von Peter bb (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

@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

von Thorsten (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Malte I. (maltomat)


Lesenswert?

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

von Thorsten (Gast)


Lesenswert?

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

von T.S. (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Thorsten (Gast)


Lesenswert?

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

von Thorsten (Gast)


Lesenswert?

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

von T.S. (Gast)


Lesenswert?

> - 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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von T.S. (Gast)


Lesenswert?

> 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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

@Torsten (ohne h)

Das mit dem TWI hatte ich überlesen. D.h. für das Messen ist auch ein
Polling nötig. Dann wird das natürlich schwieriger, ohje...

von Malte I. (maltomat)


Lesenswert?

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

von Thorsten (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von T.S. (Gast)


Lesenswert?

> 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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Malte Ibs (Gast)


Lesenswert?

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

von Malte I. (maltomat)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Uwe (Gast)


Lesenswert?

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

von Malte I. (maltomat)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

@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

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

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

von Malte I. (maltomat)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

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

von Malte I. (maltomat)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Reinhold Pieper (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Reinhold Pieper (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Reinhold Pieper (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Pete (Gast)


Lesenswert?

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 ...

von Pete (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Reinhold Pieper (Gast)


Lesenswert?

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

von Reinhold Pieper (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von T.S. (Gast)


Lesenswert?

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

von Pete (Gast)


Lesenswert?

Ich habe die gleichen Probleme :-(

von Pete (Gast)


Lesenswert?

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 ?

von T.S. (Gast)


Lesenswert?

> 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

von Avr N. (avrnix) Benutzerseite


Lesenswert?


von Pete (Gast)


Lesenswert?

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

von T.S. (Gast)


Lesenswert?

@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

von Pete (Gast)


Lesenswert?

Habe aber auch in dem Thread keine Lösung für die "Read-only"-Karten
gefunden...

von Malte Ibs (Gast)


Lesenswert?

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

von Pete (Gast)


Lesenswert?

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.

von Uwe (Gast)


Lesenswert?

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

von T.S. (Gast)


Lesenswert?

@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

von Pete (Gast)


Lesenswert?

@Torsten:
Hast Du Deine Karte wieder reaktieren können ?

Beantwortet ist auch noch nicht Deine Frage nach der Reaktivierung der
Karte ...

von Lars (Gast)


Lesenswert?

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.

von Sven Scholz (Gast)


Lesenswert?

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.

von Nik B. (nikbamert)


Lesenswert?

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

von Holger Milz (Gast)


Lesenswert?

Hi,

hat jemand schon Verzeichnisse angelegt? Ich kriege es nicht richtig hin 
und habe immer alten Datenmüll in den Verzeichnissen.

Danke!!!

Gruß
Holger

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

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

von T.S. (Gast)


Lesenswert?

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

von Funkamateur1 (Gast)


Lesenswert?

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.

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Pete (Gast)


Lesenswert?

@ T.S.:
Hast Du die defekte Karte wieder reaktivieren können oder eine Lösung 
für das Ziehen der Karte beim Schreiben gefunden ?

von Adrian (Gast)


Lesenswert?

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...

von T.S. (Gast)


Lesenswert?

@ 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

von Roland R. (roland) Benutzerseite


Lesenswert?

@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

von Pete (Gast)


Lesenswert?

@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

von Pete (Gast)


Lesenswert?

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 :-)

von emil (Gast)


Lesenswert?

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?

von Hauke Radtki (Gast)


Lesenswert?

Du musst sie nur im µC wieder zu raw dekodieren, was aber nicht äußerst 
schwer ist.

von Roland R. (roland) Benutzerseite


Lesenswert?

@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

von emil (Gast)


Lesenswert?

@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.

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

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

von M. (Gast)


Lesenswert?

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.







von Roland R. (roland) Benutzerseite


Lesenswert?

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

von M. (Gast)


Lesenswert?

Danke, klappt jetzt.

Super!
M.

von M. (Gast)


Lesenswert?

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.

von M. (Gast)


Angehängte Dateien:

Lesenswert?

Der versprochene Anhang

M.

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Pete (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

@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

von M. (Gast)


Lesenswert?

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.

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von M. (Gast)


Lesenswert?

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.

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Pete (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Mille (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Mille (Gast)


Angehängte Dateien:

Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

Ok, danke. Ich werde mir das mal anschauen, kann Dir aber noch nicht 
sagen, wann ich Zeit dafür finde.

von jeremy (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

@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

von Dirk Meyer (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

@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

von Dirk Meyer (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

@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

von Thomas (Gast)


Lesenswert?

Übrigens gute Meldung bezüglich FAT (zumindest in D):

http://www.heise.de/newsticker/meldung/86102

von Gast (Gast)


Lesenswert?

Ist Rolands Server down ? Ich bekomme keine Verbindung.

von Mille (Gast)


Lesenswert?

@Roland,

kurzes feedback.
Funktioniert alles prima!!! Super Arbeit!!! ->froi<-

Gruß
Mille

von Roland R. (roland) Benutzerseite


Lesenswert?

@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

von Roland R. (roland) Benutzerseite


Lesenswert?

So, wieder online...

:-))
Roland

von Mitrofanow (Gast)


Lesenswert?

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ß.

von Michael U. (tolle)


Lesenswert?

Hallo Roland,

wie kann ich unter Windoes XP die SD-Karte als FAT16 formatieren?

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Michael U. (tolle)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Michael U. (tolle)


Lesenswert?

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

von Hansl (Gast)


Lesenswert?

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

von (geloescht) (Gast)


Lesenswert?

(Dieser Beitrag wurde geloescht)

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von (geloescht) (Gast)


Lesenswert?

(Dieser Beitrag wurde geloescht)

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Werner B. (Gast)


Lesenswert?

Wegen SD formatieren:

Gibts bei Panasonic

http://panasonic.jp/support/audio/sd/download/sd_formatter_e.html

von (geloescht) (Gast)


Lesenswert?

(Dieser Beitrag wurde geloescht)

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von (geloescht) (Gast)


Lesenswert?

(Dieser Beitrag wurde geloescht)

von T.S. (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

@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

von Michael O. (odiwan)


Lesenswert?

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

von Michael O. (odiwan)


Lesenswert?

Hallo zusammen,

@Guido: Wieder mal zu schnell abgesendet.

Der Code geht ja noch weiter:
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
12
    #error "no sd/mmc pin mapping available!"
13
#endif
14
15
#define configure_pin_available()  DDRB &= ~(1 << PB7), PORTB |= (1<<PB7)    /* internen Pull-Up an PB7 aktivieren */
16
#define configure_pin_locked()  DDRB &= ~(1 << PB6), PORTB |= (1<<PB6)    /* internen Pull-Up an PB6 aktivieren */
17
18
#define get_pin_available() ((PINB >> PB7) & 0x01)
19
#define get_pin_locked() ((PINB >> PB6) & 0x01)

Der Pin available und locked funktionieren auf dem Arthernet auch.

Tschau
Michael

von (geloescht) (Gast)


Lesenswert?

(Dieser Beitrag wurde geloescht)

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

@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

von (geloescht) (Gast)


Lesenswert?

(Dieser Beitrag wurde geloescht)

von T.S. (Gast)


Lesenswert?

> was nehm ich da für ein Programm unter Windows?

... das gleichnamige. ;)

Wenn Du WinAVR installiert hast, guck mal unter utils\bin

Torsten

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von (geloescht) (Gast)


Lesenswert?

(Dieser Beitrag wurde geloescht)

von T.S. (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von T.S. (Gast)


Lesenswert?

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


von Roland R. (roland) Benutzerseite


Lesenswert?

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

von T.S. (Gast)


Lesenswert?

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

von Matthias (Gast)


Angehängte Dateien:

Lesenswert?

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.

von T.S. (Gast)


Lesenswert?

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

von Matthias (Gast)


Lesenswert?

Also selbst wenn ich das Timeout von 10 auf 1000 erhöh kommt immernoch 
0x3f zurück.

von Günther F. (taraquedo)


Angehängte Dateien:

Lesenswert?

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!

von T.S. (Gast)


Lesenswert?

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

von stefan richter (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Joachim (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Peter (Gast)


Lesenswert?

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...

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

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

von (geloescht) (Gast)


Lesenswert?

(Dieser Beitrag wurde geloescht)

von (geloescht) (Gast)


Lesenswert?

(Dieser Beitrag wurde geloescht)

von taraquedo (Gast)


Lesenswert?

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!

von August (Gast)


Lesenswert?

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

von Stefan (Gast)


Lesenswert?

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

von Slater (Gast)


Lesenswert?

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

von Hansl (Gast)


Lesenswert?

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

von Hansl (Gast)


Lesenswert?

btw. mit 4 dioden komm ich auf 3.7V

gibts unterschiedliche 1N4148er ?

von jemand (Gast)


Lesenswert?

RTFM.

Wenn du das Datenblatt gelesen hättest, wüsstest du, dass der 
Spannungsabfall vom Strom abhängig ist, der durch die Diode fliesst.

von Hansl (Gast)


Lesenswert?

jemand: merci, habs eben nachgemessen. stimmt.

von holger (Gast)


Lesenswert?

@ 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 :(

von Hansl (Gast)


Lesenswert?

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

von T.S. (Gast)


Lesenswert?

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

von Hansl (Gast)


Lesenswert?

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

von Joachim (Gast)


Lesenswert?

> 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

von Hansl (Gast)


Lesenswert?

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

von Wolfgang (Gast)


Lesenswert?

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.

von Joachim (Gast)


Lesenswert?

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

von Hansl (Gast)


Lesenswert?

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





von Hansl (Gast)


Lesenswert?

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

von Werner B. (Gast)


Lesenswert?

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)

von Hansl (Gast)


Lesenswert?

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 ;)

von Joachim (Gast)


Lesenswert?

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



von Hansl (Gast)


Lesenswert?

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


von Joachim (Gast)


Lesenswert?

> 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

von Hansl (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Hansl (Gast)


Lesenswert?

zur hardware... hab einfach mosi und miso verbunden.
ansonst, alles beim alten, atmega16@8Mhz(interner taktgeber), stk500
fuses:Fuse Low Byte = 0xd4, Fuse High Byte = 0xd9

mfg
 Hansl

von Hansl (Gast)


Lesenswert?

ok, klappt doch,

hab vergessen das ueberfluessige zeug auszukommentieren :)

nungut. also spi funktioniert also grundsaetzlich.


aendeurng in main.c von zuvor:

uint8_t sd_raw_rec_byte()
{
    /* send dummy data for receiving some */
//    SPDR = 0xff;
//    while(!(SPSR & (1 << SPIF)));
//    SPSR &= ~(1 << SPIF);
    return SPDR;
}


mfg
 Hansl

von Joachim (Gast)


Lesenswert?

> 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

von Hansl (Gast)


Lesenswert?

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

von Hansl (Gast)


Angehängte Dateien:

Lesenswert?

....

von Joachim (Gast)


Lesenswert?

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:
1
#define configure_pin_available() DDRC &= ~(1 << DDC4)
2
#define get_pin_available() ((PINC >> PC4) & 0x01)

In der sd_raw.c wird dies überall abgefragt.
Die Funktion dazu:
1
* \ingroup sd_raw
2
 * Checks wether a memory card is located in the slot.
3
 * \returns 1 if the card is available, 0 if it is not.
4
 */
5
uint8_t sd_raw_available()
6
{
7
    return get_pin_available() == 0x00;
8
}

Ich habe die bei mir geändert, weil ich auch keine Kartenerkennung 
benutze und dies zur Fehlermeldung geführt hätte:
1
uint8_t sd_raw_available()
2
{
3
    return 1; //get_pin_available() == 0x00;
4
}

Probier das mal.
Leider hast Du die konkrete Verdrahtung der Karte erst jetzt gepostet, 
sonst wäre mir das schon eher aufgefallen.

Joachim

von Hansl (Gast)


Lesenswert?

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

von Joachim (Gast)


Lesenswert?

Tja, dann bin ich auch am Ende meiner Weisheit.
Sorry.

Joachim

von Richard Brose (Gast)


Lesenswert?

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?

von Andreas W. (Gast)


Lesenswert?

@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

von Marcus H. (Firma: www.harerod.de) (lungfish) Benutzerseite


Lesenswert?

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).

von Joachim (Gast)


Lesenswert?

> ..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

von Andreas W. (Gast)


Angehängte Dateien:

Lesenswert?

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.

von michi (Gast)


Lesenswert?

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

von holger (Gast)


Lesenswert?

>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.

von michi (Gast)


Lesenswert?

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?

von (geloescht) (Gast)


Lesenswert?

(Dieser Beitrag wurde geloescht)

von michi (Gast)


Lesenswert?

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?

von holger (Gast)


Lesenswert?

>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.

von michi (Gast)


Lesenswert?

>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!

von Niklas Eriksson (Gast)


Lesenswert?

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

von Andreas W. (beinhartplus)


Lesenswert?

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 ?

von Werner B. (Gast)


Lesenswert?

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.

von Robero (Gast)


Lesenswert?

Hallo,
Super Projekt!!!
ist es irgendwie möglich das es auch auf nem Atmega8 Funktioniert?
Gruß Robert

von Karl (Gast)


Lesenswert?

@ 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

von ptiszai (Gast)


Lesenswert?

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

von Steffen-SD (Gast)


Lesenswert?

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??

von Joachim Müller (Gast)


Lesenswert?

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

von Karoly K. (koka55)


Lesenswert?

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

von Gast (Gast)


Lesenswert?

Hallo Leute

Wie kann man 2 Dateien gleichzeitig öffnen?

Danke und Gruss


So geht es nicht....
1
struct fat16_file_struct* fd1 = open_file_in_dir(fs, dd, "temp.txt");
2
if(!fd1)
3
{
4
 uart_puts_p(PSTR("error opening1 "));
5
}
6
7
//search file in current directory and open it 
8
struct fat16_file_struct* fd2 = open_file_in_dir(fs, dd, "temp2.txt");
9
if(!fd2)
10
{
11
 uart_puts_p(PSTR("error opening2 "));
12
}

von Gast (Gast)


Lesenswert?

Muss ich etwa 2 Partitionen machen und jedes File aus einer anderen 
Partionion auslesen? (geht doch sicherlich auch noch einfacher)

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo,

Kurz gesagt: RTFM!

In fat16_config.h:
  #define FAT16_FILE_COUNT 2

Gruß,
Roland

von Christian S. (stephanc)


Lesenswert?

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
int main()
2
{...
3
/* print some card information as a boot message */
4
print_disk_info(fs);
5
...}

Versuch:
1
void test(void);
2
int main()
3
{...
4
/* print some card information as a boot message */
5
//print_disk_info(fs);
6
test();
7
...}
8
9
void test()
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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Karoly K. (koka55)


Lesenswert?

Hallo Roland,

Kónntest Du bitte evtl. meine Frage auch beantworten? (Siehe 20.11.2007 
09:33)

Danke,
Karoly

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Micha (Gast)


Lesenswert?

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

von Kai Bankett (Gast)


Lesenswert?

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

von Micha (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Joachim (Gast)


Lesenswert?

> Windows erzeugt meines Wissens nach eine Superfloppy.

Nee, macht auch ne Partition.

Joachim

von Karoly K. (koka55)


Lesenswert?

@Roland: Danke für die Hilfe, ich werde es unbedingt austesten!

Karoly

von Kai Bankett (Gast)


Lesenswert?

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.

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Torsten S. (tse)


Lesenswert?

> 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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Kai Bankett (Gast)


Lesenswert?

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.

von Kai Bankett (Gast)


Lesenswert?

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

von Kai Bankett (Gast)


Angehängte Dateien:

Lesenswert?

Hier nun hoffentlich mit Attachment ...

von Torsten S. (tse)


Lesenswert?

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

von Kai Bankett (Gast)


Lesenswert?

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 ...

von Torsten S. (tse)


Lesenswert?

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:
1
+debug(S_PSTR("CHAOSMAN D0"));
2
+#ifdef DEBuG_FAT16

von Kai B. (chaosman)


Lesenswert?

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:
>
1
+debug(S_PSTR("CHAOSMAN D0"));
2
> +#ifdef DEBuG_FAT16

Ja, danke! Ist korriegiert.

Kai

von Martin (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Martin (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Martin (Gast)


Angehängte Dateien:

Lesenswert?

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

von Bernhard S. (bernhard)


Lesenswert?

Hallo,

ein ATmega8 bedient eine SD-Karte (FAT16), ist allerdings nur Assembler:

Beitrag "SD-Karte Initialisierung Read Write FAT ATmega8 (Assembler)"


Gruß

Bernhard

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Martin (Gast)


Angehängte Dateien:

Lesenswert?

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

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

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:
1
00048c00  41 31 00 00 00 ff ff ff  ff ff ff 0f 00 6c ff ff  |A1...........l..|
2
00048c10  ff ff ff ff ff ff ff ff  ff ff 00 00 ff ff ff ff  |................|
3
00048c20  31 20 20 20 20 20 20 20  20 20 20 00 00 00 00 00  |1          .....|
4
00048c30  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
5
00048c40  41 32 00 00 00 ff ff ff  ff ff ff 0f 00 2c ff ff  |A2...........,..|
6
00048c50  ff ff ff ff ff ff ff ff  ff ff 00 00 ff ff ff ff  |................|
7
00048c60  32 20 20 20 20 20 20 20  20 20 20 00 00 00 00 00  |2          .....|
8
00048c70  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
9
00048c80  41 33 00 00 00 ff ff ff  ff ff ff 0f 00 ec ff ff  |A3..............|
10
00048c90  ff ff ff ff ff ff ff ff  ff ff 00 00 ff ff ff ff  |................|
11
00048ca0  33 20 20 20 20 20 20 20  20 20 20 00 00 00 00 00  |3          .....|
12
00048cb0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
13
...

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

von stucmath (Gast)


Lesenswert?

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

von Martin (Gast)


Lesenswert?

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:
1
0000b000  41 64 00 61 00 74 00 65  00 69 00 0f 00 ae 2e 00  |Ad.a.t.e.i......|
2
0000b010  31 00 00 00 ff ff ff ff  ff ff 00 00 ff ff ff ff  |1...............|
3
0000b020  64 61 74 65 69 20 20 20  31 20 20 00 00 00 00 00  |datei   1  .....|
4
0000b030  00 00 00 00 00 00 00 00  00 00 02 00 08 00 00 00  |................|
5
0000b040  41 64 00 61 00 74 00 65  00 69 00 0f 00 6f 2e 00  |Ad.a.t.e.i...o..|
6
0000b050  32 00 00 00 ff ff ff ff  ff ff 00 00 ff ff ff ff  |2...............|
7
0000b060  64 61 74 65 69 20 20 20  32 20 20 00 00 00 00 00  |datei   2  .....|
8
0000b070  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
9
(...)
10
0000b1c0  41 64 00 61 00 74 00 65  00 69 00 0f 00 b0 2e 00  |Ad.a.t.e.i......|
11
0000b1d0  38 00 00 00 ff ff ff ff  ff ff 00 00 ff ff ff ff  |8...............|
12
0000b1e0  64 61 74 65 69 20 20 20  38 20 20 00 00 00 00 00  |datei   8  .....|
13
0000b1f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
14
0000b200  41 64 00 61 00 74 00 65  00 69 00 0f 00 f0 2e 00  |Ad.a.t.e.i......|
15
0000b210  39 00 00 00 ff ff ff ff  ff ff 00 00 ff ff ff ff  |9...............|
16
0000b220  64 61 74 65 69 20 20 20  39 20 20 00 00 00 00 00  |datei   9  .....|
17
0000b230  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
18
*
19
0000f000  48 61 6c 6c 6f 6c 65 21  00 00 00 00 00 00 00 00  |Hallole!........|
20
0000f010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|

Da scheint bei meinen Versionen von sd_raw_send_byte() und 
sd_raw_rec_byte() der Wurm drin zu sein!

Gruß Martin

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

@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

von stucmath (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Martin (Gast)


Lesenswert?

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

von stucmath (Gast)


Lesenswert?

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

von Malte (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

@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

von Ing. (Gast)


Lesenswert?

Hallo Roland,

danke für die schnelle Antwort. Bei mir kommt statt der Dioden ein LM317 
zum Einsatz der die 3,3V bereitstellt.
Komisch...


Gruß
Malte

von stucmath (Gast)


Lesenswert?

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

von Malte (Gast)


Lesenswert?

Danke, werde ich mir mal ansehen.

von Malte (Gast)


Lesenswert?

Also, ich habe das eben durchgemessen. DI, CS, CLK liegen alle bei 3,2V. 
Versorgungspannung bei 3,29V)

Bin reichlich ratlos...

Malte

von Torsten S. (tse)


Lesenswert?

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

von Reinhard N. (rn-cologne)


Lesenswert?

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
1
#define get_pin_available() 1   // Change ((PINC >> PC4) & 0x01)
2
#define get_pin_locked() 1      // Change ((PINC >> PC5) & 0x01)

und in sd_raw.c
1
uint8_t sd_raw_available()
2
{
3
    return 1;  // change get_pin_available() == 0x00;
4
}
5
6
7
uint8_t sd_raw_locked()
8
{
9
    return 0;  // change get_pin_locked() == 0x00;
10
}
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

von Martin (Gast)


Lesenswert?

Hallo Reinhard,

in Deiner sd_raw_config.h sollte folgendes stehen (s.a. weiter oben):
1
#define configure_pin_available()
2
#define configure_pin_locked()
3
#define get_pin_available() 0
4
#define get_pin_locked() 0
Damit kannst Du die originalen sd_raw_locked() und sd_raw_available() 
unverändert lassen. Mit Deinem:
1
#define get_pin_locked() 1
wird sd_raw_write() nie ausgeführt (s. sd_raw.c).

Gruß
Martin

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Reinhard N. (rn-cologne)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Reinhard N. (rn-cologne)


Lesenswert?

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
1
    if(!device_read_interval(header->root_dir_offset,
2
                             buffer,
3
                             sizeof(buffer),
4
                             header->cluster_zero_offset - header->root_dir_offset,
5
                             fat16_dir_entry_seek_callback,
6
                             &arg) ||
7
       arg.entry_offset == 0
8
      )
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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Kai F. (kai-) Benutzerseite


Lesenswert?

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

von Kai F. (kai-) Benutzerseite


Lesenswert?

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?

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Kai F. (kai-) Benutzerseite


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

@ 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

von Reinhard N. (rn-cologne)


Lesenswert?

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
> cat 2.txt
13
00000000: 20 0a 02 00 00 00 00 00
14
> write 2.txt 0
15
< jetzt funkt's
16
< danke an Roland
17
<
18
> cat 2.txt
19
00000000: 6a 65 74 7a 74 20 66 75
20
00000008: 6e 6b 74 27 73 64 61 6e
21
00000010: 6b 65 20 61 6e 20 52 6f
22
00000018: 6c 61 6e 64 6e 20 52 6f
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

von holger (Gast)


Lesenswert?

>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 !

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Torsten S. (tse)


Lesenswert?

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

von Reinhard N. (rn-cologne)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Mathias S. (stucmath)


Lesenswert?

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

von Kai B. (chaosman)


Lesenswert?

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

von Mathias S. (stucmath)


Lesenswert?

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

von EDAconsult Udo Kuhn (Gast)


Angehängte Dateien:

Lesenswert?

@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

von Gast (Gast)


Lesenswert?

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

von EDAconsult Udo Kuhn (Gast)


Lesenswert?

Hallo Gast,

ganz oben als erstes steht sie, vom Entwickler selbst. Dann nur noch 
alles genau lesen und schon geht es los.

von Roland R. (roland) Benutzerseite


Lesenswert?

@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

von EDAconsult Udo Kuhn (Gast)


Angehängte Dateien:

Lesenswert?

@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

von Jan (Gast)


Lesenswert?

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.

von Roland R. (roland) Benutzerseite


Lesenswert?

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.

von Malte (Gast)


Angehängte Dateien:

Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Malte,

Normalerweise sollten da schon neun Bytes geschrieben werden. Was gibt 
denn fat16_write_file() zurück? Immer den Rückgabewert mit der Anzahl zu 
schreibender Bytes vergleichen! Sonst kann man sich nie sicher sein, 
dass wirklich alle Bytes geschrieben wurden. [1]

Ansonsten: Benutzt Du SD_RAW_WRITE_BUFFERING? Wenn ja, musst Du vor dem 
Entfernen der Karte sd_raw_sync() ausführen! [2]

Gruß,
Roland

[1] 
http://www.roland-riegel.de/sd-reader/doc/group__fat16__file.html#g4f0c785a47b1cf070839b5edec2c6f65
[2] 
http://www.roland-riegel.de/sd-reader/doc/group__sd__raw.html#gd4d9ff40a7ea50c65cfa47927b35b735

von Malte (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Malte (Gast)


Lesenswert?

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

von pito (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

@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

von Thomas B. (froms)


Lesenswert?

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

von Torsten S. (tse)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

@Torsten,

Danke, aber vorgestellt habe ich es doch :)
Beitrag "Erweiterbares Ethernetboard mit MMC/SD-Slot und USB"

Gruß,
Roland

von Thomas B. (froms)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Thomas B. (froms)


Lesenswert?

@ 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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Torsten S. (tse)


Lesenswert?

Roland Riegel wrote:

> Danke, aber vorgestellt habe ich es doch :)
> Beitrag "Erweiterbares Ethernetboard mit MMC/SD-Slot und USB"

Opps. Das habe ich irgendwie übersehen...

Torsten

von Thomas B. (froms)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

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

von Mathias S. (stucmath)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Mathias S. (stucmath)


Lesenswert?

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
struct fat16_dir_struct* dir = 0;
2
3
while (1)
4
{
5
  if (Taster_Enter_pos_F)
6
  {
7
    struct fat16_dir_entry_struct file_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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Pito (Gast)


Lesenswert?

Hi Roland,
does the cd command in the newest sd-reader_source_20080608 work?

> mkdir rrr
> ls
rrr/                                 0
> cd rrr
directory not found: rrr

Gruss,
Pito

von Pito (Gast)


Lesenswert?

Hi,
cd works until you provide "init". Than cd stops to work..
Pito

von MarkusW (Gast)


Lesenswert?

Hallo!

Ich habe hier eine sagenhafte 8 MB(!)-SD Karte.
Erst funktionierte sie nicht, bis ich die Abfrage auf
1
 if(data_cluster_count < 4085 || data_cluster_count >= 65525)

gefunden und das entsprechende "< 4085" auskommentiert habe. So viele 
Cluster gibt es anscheinend auf einer 8MB-Karte nicht.


Jetzt habe ich aber das Problem, dass ich auf der frisch formatierten 
Karte eine Datei anlegen will (und dort auch etwas reinschreibe) und die 
Datei dann in Windows aber nicht gelesen werden kann (über das 
UART-Interface geht´s aber).
Ich führe dann ein CheckDisk ("Auf Fehler überprüfen") durch, was die 
Datei (meistens) wieder herstellt.
Danach kann ich auch weitere Dateien anlegen, die dann problemlos 
gelesen werden können.

Hier noch die Karteninfo:
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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von MarkusW (Gast)


Lesenswert?

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

von MarkusW (Gast)


Lesenswert?

Hallo, ich bin´s nochmal...

komme gerade nicht so richtig weiter.

Er bleibt an dieser Stelle hängen:
1
uint8_t fat16_read_header(struct fat16_fs_struct* fs)
2
{
3
    if(!fs)
4
        return 0;
5
6
    struct partition_struct* partition = fs->partition;
7
    if(!partition)
8
        return 0;
9
10
    /* read fat parameters */
11
    uint8_t buffer[25];
12
    uint32_t partition_offset = partition->offset * 512;
13
---------------------------------------------
14
    if(!partition->device_read(partition_offset + 0x0b, buffer, sizeof(buffer)))
15
  {
16
       return 0;
17
  }

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

von MarkusW (Gast)


Lesenswert?

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?

von niketchana (Gast)


Lesenswert?

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

von niketchana (Gast)


Lesenswert?

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

von Gast (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Gast (Gast)


Lesenswert?

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

von pito (Gast)


Lesenswert?

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.

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von pito (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von hihi (Gast)


Lesenswert?

Diese Fragen kenn ich von der Arbeit. g Da wird dann debug-code ganz 
schnell mal vergewohltätigt.

von pito (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

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

von Torsten S. (tse)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Torsten S. (tse)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Werner B. (werner-b)


Lesenswert?

@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?

von Werner B. (werner-b)


Lesenswert?

> P.S. raw_entry[11] == 0x0f
>      Was steckt dahinter?

Selbst beantwortet:
Attribute "Read-only, System, Hidden, and Volume" == LFN Entry

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Werner B. (werner-b)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

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

von Werner B. (werner-b)


Lesenswert?

Hallo Roland,

klappt hervorragend.

Danke!

Werner

von Torsten S. (tse)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

@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

von Klaus M. (meinzinet)


Lesenswert?

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.

von Werner B. (werner-b)


Lesenswert?

Wird die Datei denn vor dem entnehmen der Karte geschlossen?
1
fat_close_file(sd_file);
2
fat_close_dir(sd_dd);
3
fat_close(sd_fs);
4
partition_close(sd_partition);

von Klaus M. (meinzinet)


Lesenswert?

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?

von Klaus M. (meinzinet)


Lesenswert?

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.

von Klaus M. (meinzinet)


Lesenswert?

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.

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Werner B. (werner-b)


Lesenswert?

Hmmm,

ich habe den Code nicht zur Hand, aber
eigentlich sollte sd_raw_sync() spätestens in fat_close() automatisch 
aufgerufen werden.

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Klaus M. (meinzinet)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Klaus M. (meinzinet)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Klaus,

Na dann hab ich ja ins Schwarze getroffen. Schön, dass es jetzt 
funktioniert.

Viele Grüße,
Roland

von Torsten S. (tse)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Esther L. (lara)


Lesenswert?

Hallo,
Ich hatte am Anfang auch Probleme aber nun klappt es bei mir.
sd_raw_config.h:
#define get_pin_available() (PINB & ( 1 << PB4)) // CD von SDC
#define get_pin_locked() (PINB & ( 1 << PB5))    // WP von SDC
...

in sd_raw.c :
uint8_t sd_raw_available()
{
  if(get_pin_available())
    return 1;
  else
    return 0;
}
uint8_t sd_raw_locked()
{
if(get_pin_locked())
    return 0;
  else
    return 1;
}
uint8_t sd_raw_write(uint32_t offset, const uint8_t* buffer, uint16_t 
length)
{
#if SD_RAW_WRITE_SUPPORT

    if(!(get_pin_locked()))
        return 0;
...
als Abfrage:
void GetSDCstatus(void){
  if (sd_raw_available()){ // SD-Karte eingesteckt
    lcd_puts("* SD Card detected *");
    if (sd_raw_locked())
  lcd_puts("!    WP enable     !");// Schreibschutz aktiviert
  }
  else
    lcd_puts("!  No SDC detected !");
}

von Torsten S. (tse)


Lesenswert?

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

von Birger Z. (nohelp)


Lesenswert?

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.

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Klaus M. (meinzinet)


Lesenswert?

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.

von Birger Z. (nohelp)


Lesenswert?

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.

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von No Name (Gast)


Lesenswert?

Meine beiden SD-Karten sind 128MB und 2GB groß, hätten also doch auch 
ohne Änderung funktionieren müssen. Oder sehe ich das falsch?

von meini (Gast)


Lesenswert?

Also meine 2GB und 1GB SD Karten haben auf Anhieb funktioniert!
Also kann es wohl nicht an der Software liegen!
Oder sehe ich das falsch?

von Gerd (Gast)


Lesenswert?

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

von meini (Gast)


Lesenswert?

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)

von Birger Z. (nohelp)


Lesenswert?

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.

von meini (Gast)


Angehängte Dateien:

Lesenswert?

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

von Gerd (Gast)


Lesenswert?

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

von meini (Gast)


Lesenswert?

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

von Torsten S. (tse)


Lesenswert?

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

von Gerd (Gast)


Lesenswert?

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:
1
//############################################################################
2
//Routine zur Initialisierung der MMC/SD-Karte (SPI-MODE)
3
unsigned char mmc_init ()
4
//############################################################################
5
{
6
  unsigned int Timeout = 0;
7
  
8
  //Konfiguration des Ports an der die MMC/SD-Karte angeschlossen wurde
9
  MMC_Direction_REG &=~(1<<SPI_DI);      //Setzen von Pin MMC_DI auf Input
10
  MMC_Direction_REG |= (1<<SPI_Clock);    //Setzen von Pin MMC_Clock auf Output
11
  MMC_Direction_REG |= (1<<SPI_DO);      //Setzen von Pin MMC_DO auf Output
12
  MMC_Direction_REG |= (1<<MMC_Chip_Select);  //Setzen von Pin MMC_Chip_Select auf Output
13
  MMC_Direction_REG |= (1<<SPI_SS);  
14
  MMC_Write |= (1<<MMC_Chip_Select);      //Setzt den Pin MMC_Chip_Select auf High Pegel
15
16
  for(unsigned char a=0;a<200;a++){
17
  nop();
18
  };    //Wartet eine kurze Zeit
19
20
  #if SPI_Mode
21
    //Aktiviren des SPI - Bus, Clock = Idel LOW
22
    //SPI Clock teilen durch 128
23
    SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1); //Enable SPI, SPI in Master Mode  
24
    SPSR = (0<<SPI2X);
25
  #endif
26
  
27
  //Initialisiere MMC/SD-Karte in den SPI-Mode
28
  for (unsigned char b = 0;b<0x0f;b++) //Sendet min 74+ Clocks an die MMC/SD-Karte
29
    {
30
    mmc_write_byte(0xff);
31
    }
32
  
33
  //Sendet Commando CMD0 an MMC/SD-Karte
34
  unsigned char CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95};
35
  while(mmc_write_command (CMD) !=1)
36
  {
37
    if (Timeout++ > 200)
38
      {
39
      MMC_Disable();
40
      return(1); //Abbruch bei Commando1 (Return Code1)
41
      }
42
  }
43
  //Sendet Commando CMD1 an MMC/SD-Karte
44
  Timeout = 0;
45
  CMD[0] = 0x41;//Commando 1
46
  CMD[5] = 0xFF;
47
  while( mmc_write_command (CMD) !=0)
48
  {
49
    if (Timeout++ > 400)
50
      {
51
      MMC_Disable();
52
      return(2); //Abbruch bei Commando2 (Return Code2)
53
      }
54
  }
55
  #if SPI_Mode
56
    //SPI Bus auf max Geschwindigkeit
57
    SPCR &= ~((1<<SPR0) | (1<<SPR1));
58
    SPSR = SPSR|(1<<SPI2X);
59
  #endif
60
  
61
  //set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
62
  MMC_Disable();
63
  return(0);
64
}
Ich melde mich wieder, wenn ich das andere Problem gelöst habe.

Gruß Gerd

von Toblachs (Gast)


Lesenswert?

Hey,

mal ne ganz andere Frage. Hat schon mal jemand probiert das
ganze in Assembler zu programmieren?

von Birger Z. (nohelp)


Lesenswert?

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.

von Daniel B. (dbuergin)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Daniel B. (dbuergin)


Lesenswert?

Super, besten Dank

Daniel

von Alexander H. (sonium)


Lesenswert?

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.

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Alexander H. (sonium)


Lesenswert?

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.

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Gast (Gast)


Lesenswert?

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.

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Gast (Gast)


Lesenswert?

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

von Gast (Gast)


Lesenswert?

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.

von Marcel (Gast)


Lesenswert?

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
global void vSD_Init(void)
2
{
3
  uint8 buffer[24];
4
5
  if(sd_raw_init() == TRUE)
6
  {
7
    vLCD_Control(ZEILE_1, "SD-Card found");
8
9
    // open first partition 
10
        struct partition_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
21
             * is a "superfloppy", i.e. has no MBR.
22
             */
23
            partition = partition_open(
24
              sd_raw_read,
25
                            sd_raw_read_interval,
26
                            /*sd_raw_write*/ 0,
27
                            /*sd_raw_write_interval*/ 0,
28
                            -1
29
                            );  
30
      if(partition == FALSE)
31
            {
32
                vLCD_Control(ZEILE_1, "opening partition failed");
33
            }
34
        }
35
    
36
    // open file system 
37
        struct fat_fs_struct* fs = fat_open(partition);
38
        if(fs == FALSE)
39
        {
40
            vLCD_Control(ZEILE_1, "opening filesystem failed");
41
        }
42
    else
43
    {
44
      // open root directory 
45
          struct fat_dir_entry_struct directory;
46
          fat_get_dir_entry_of_path(fs, "/", &directory);
47
48
          struct fat_dir_struct* dd = fat_open_dir(fs, &directory);
49
          if(dd == FALSE)
50
          {
51
              vLCD_Control(ZEILE_2, "opening root directory failed");
52
          }
53
      else
54
      {
55
        // print some card information as a boot message
56
            print_disk_info(fs);
57
    
58
        // search file in current directory and open it 
59
            struct fat_file_struct* fd = open_file_in_dir(fs, dd, "test.txt");
60
            if(!fd)
61
            {
62
              vLCD_Control(ZEILE_2, "error opening ");
63
            }
64
        else
65
        {  
66
          fat_read_file(fd, buffer, sizeof(buffer));
67
         }
68
      }
69
    }  
70
  }
71
  else
72
  {    // Init of SD-Card failed
73
    vLCD_Control(ZEILE_1, "SD-Card failed");  
74
  }
75
}

von Torsten S. (tse)


Lesenswert?

Es könnte ein Problem mit der Schreibweise sein. Wenn diese Datei unter 
Windows erstellt wurde, probier mal:
1
struct fat_file_struct* fd = open_file_in_dir(fs, dd, "test.TXT");

Torsten

von Marcel (Gast)


Lesenswert?

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?

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Stefan (Gast)


Lesenswert?

Hallo Roland,

erstmal klasse, daß du uns dieses Projekt zur Verfügung stellst...habe 
dennoch ein kleines Problem mit sd_raw.c:
1
    /* wait for card to get ready */
2
    for(uint16_t i = 0; ; ++i)
3
    {
4
5
        if(sd_raw_card_type & ((1 << SD_RAW_SPEC_1) | (1 << SD_RAW_SPEC_2)))
6
        {
7
            uint32_t arg = 0;
8
#if SD_RAW_SDHC
9
            if(sd_raw_card_type & (1 << SD_RAW_SPEC_2))
10
                arg = 0x40000000;
11
#endif
12
            sd_raw_send_command(CMD_APP, 0);
13
            response = sd_raw_send_command(CMD_SD_SEND_OP_COND, arg);
14
        }
15
        else
16
        {
17
            response = sd_raw_send_command(CMD_SEND_OP_COND, 0);
18
        }
19
20
        if((response & (1 << R1_IDLE_STATE)) == 0)
21
    {
22
            break;
23
    }
24
25
        if(i == 0x7fff)
26
        {
27
            unselect_card();
28
            return 0;
29
        }
30
    }

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Marcel (Gast)


Lesenswert?

Abend,

Problem gelöst --> vielen Dank
Es muss
1
 
2
struct fat_file_struct* fd = open_file_in_dir(fs, dd, "TEST.TXT");
heißen.

Der Tipp mit dem Auflisten der Dateien auf der Karte hat voll ins 
Schwarze getroffen.

Auch wenn trivial, da wäre ich nie alleine drauf gekommen ;)

SChönes Wochenende

von Michael W. (das-micha)


Lesenswert?

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 ;-)

von Gast (Gast)


Lesenswert?

Schau Dir mal die Exportieren-Funktion von Eagle an.
(Datei->Exportieren->Image)

Ansonsten ausdrucken und z.B. freepdfxp benutzen.

von Stefan (Gast)


Lesenswert?

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

von Michael W. (das-micha)


Lesenswert?

ähm ja, aber ich haben gar kein eagle ... das ist das problem ....

von Gast (Gast)


Lesenswert?

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.

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Alex (Gast)


Lesenswert?

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

von Alex (Gast)


Lesenswert?

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!

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Alex (Gast)


Lesenswert?

Roland,

vielen dank!

Grüße
Alex

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

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

von Jan (Gast)


Lesenswert?

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.
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
      }
13
14
    struct fat_file_struct * file = fat_open_file(fs,&directory);
15
    if(!file)
16
    {
17
      uart_puts_p(PSTR("file error\n"));
18
    }
19
    else
20
    {
21
      uart_puts_p(PSTR("file ok\n"));
22
    }
23
24
    
25
    char write[] = "test";
26
    
27
    int data_len = 1+strlen(write);
28
    
29
    if(fat_write_file(file, (uint8_t*) write, data_len) != data_len)
30
    {
31
      uart_puts_p(PSTR("error writing to file\n"));
32
      break;
33
    }
34
    else
35
    {
36
      uart_puts("file beschrieben \n");
37
    }
38
39
    
40
    fat_close_file (file);
41
42
    return 0;

von Roland R. (roland) Benutzerseite


Lesenswert?

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?
1
>     struct fat_file_struct * file = fat_open_file(fs,&directory);
2
>     if(!file)
3
>     {
4
>       uart_puts_p(PSTR("file error\n"));
5
>     }
6
>     else
7
>     {
8
>       uart_puts_p(PSTR("file ok\n"));
9
>     }

Was passiert nach einem Fehler beim Öffnen der Datei? Du machst schon 
wieder einfach weiter!
1
>     char write[] = "test";
2
> 
3
>     int data_len = 1+strlen(write);

Warum "+1"? Willst Du das Null-Byte am Ende des Strings wirklich in der 
Datei haben?
1
>     if(fat_write_file(file, (uint8_t*) write, data_len) != data_len)
2
>     {
3
>       uart_puts_p(PSTR("error writing to file\n"));
4
>       break;
5
>     }

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

von Thorsten S. (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Thorsten S. (Gast)


Lesenswert?

Windos sagt FAT, Linux habe ich nicht installiert. Werde die 
UART-Ausgaben mal verfeinern. Der Code ist die aktuelle Lib von Deiner 
Homepage.

von Thorsten S. (Gast)


Lesenswert?

Habe jetzt mal Winhex installiert und siehe da, es ist FAT12.

Schade, da muss ich wohl noch mal schauen, wie ich das Format ändern 
kann.

von Simon K. (simon) Benutzerseite


Lesenswert?

Hallo,

Eine Anmerkung und eine Frage:
1
void sd_raw_send_byte(uint8_t b)
2
{
3
    SPDR = b;
4
    /* wait for byte to be shifted out */
5
    while(!(SPSR & (1 << SPIF)));
6
    SPSR &= ~(1 << SPIF);
7
}

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!

von Thorsten S. (Gast)


Lesenswert?

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.
1
 /* setup sd card slot */
2
 if(!sd_raw_init())
3
 {
4
    uart_puts_p(PSTR("MMC/SD initialization failed\n"));
5
    _delay_ms(20);
6
    return 0;
7
 }
8
9
 /* open first partition */
10
 struct partition_struct* partition = partition_open(sd_raw_read,
11
                                                            sd_raw_read_interval,
12
                            #if SD_RAW_WRITE_SUPPORT
13
                                                            sd_raw_write,
14
                                                            sd_raw_write_interval,
15
                            #else
16
                                                            0,
17
                                                            0,
18
                            #endif
19
                                                            0
20
                                                           );
21
22
        if(!partition)
23
        {
24
            /* If the partition did not open, assume the storage device
25
             * is a "superfloppy", i.e. has no MBR.
26
             */
27
            partition = partition_open(sd_raw_read,
28
                                       sd_raw_read_interval,
29
                  #if SD_RAW_WRITE_SUPPORT
30
                                       sd_raw_write,
31
                                       sd_raw_write_interval,
32
                  #else
33
                                       0,
34
                                       0,
35
                  #endif
36
                                       -1
37
                                      );
38
            if(!partition)
39
            {
40
                uart_puts("opening partition failed\n");          
41
            }
42
        }
43
44
45
        /* open file system */
46
        struct fat_fs_struct* fs = fat_open(partition);
47
        if(!fs)
48
        {
49
            uart_puts("opening filesystem failed\n");
50
            
51
        }

Und hier der Code aus fat.c:
1
struct fat_fs_struct* fat_open(struct partition_struct* partition)
2
{
3
uart_puts("fat_open\n");
4
5
    if(!partition ||
6
#if FAT_WRITE_SUPPORT
7
       !partition->device_write ||
8
       !partition->device_write_interval
9
#else
10
       0
11
#endif
12
      )
13
        return 0;
14
uart_puts("1\n");

Die 1 sehe ich jedenfalls nicht mehr in der Debug-Ausgabe.

von Thorsten S. (Gast)


Lesenswert?

Karten sind jetzt auch Fat16 formatiert.

von Simon K. (simon) Benutzerseite


Lesenswert?

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
        return 0;
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.

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Simon,

Simon K. wrote:
> Eine Anmerkung und eine Frage:
>
1
> void sd_raw_send_byte(uint8_t b)
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

von Simon K. (simon) Benutzerseite


Lesenswert?

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.

von Roland R. (roland) Benutzerseite


Lesenswert?

Servus Thorsten,

Das hier...
1
> /* open first partition */
2
> struct partition_struct* partition = partition_open(
3
>     sd_raw_read,
4
>     sd_raw_read_interval,
5
> #if SD_RAW_WRITE_SUPPORT
6
>     sd_raw_write,
7
>     sd_raw_write_interval,
8
> #else
9
>     0,
10
>     0,
11
> #endif
12
>     0
13
> );
14
> 
15
> /* ... */
16
>
17
> /* open file system */
18
> struct fat_fs_struct* fs = fat_open(partition);
19
> if(!fs)
20
> {
21
>     uart_puts("opening filesystem failed\n");
22
> }

... in Verbindung damit...
1
> struct fat_fs_struct* fat_open(struct partition_struct* partition)
2
> {
3
> uart_puts("fat_open\n");
4
> 
5
>     if(!partition ||
6
> #if FAT_WRITE_SUPPORT
7
>        !partition->device_write ||
8
>        !partition->device_write_interval
9
> #else
10
>        0
11
> #endif
12
>       )
13
>         return 0;
14
> uart_puts("1\n");

... sagt mir, dass Du zwar FAT_WRITE_SUPPORT auf 1 gesetzt hast, 
SD_RAW_WRITE_SUPPORT aber auf 0 steht.

Viele Grüße,
Roland

von Thorsten S. (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Simon K. (simon) Benutzerseite


Lesenswert?

So, bei mir läuft jetzt auch alles wie gewünscht. :-)

von Thorsten S. (Gast)


Lesenswert?

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.

von Roland R. (roland) Benutzerseite


Lesenswert?

@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

von Jan (Gast)


Lesenswert?

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
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
11
                                       -1
12
                                      );
13
            if(!partition)
14
            {
15
16
                uart_puts_p(PSTR("opening partition failed\n"));
17
18
                continue;
19
            }
20
      else
21
      {
22
        uart_puts_p(PSTR("partition open \n"));
23
        
24
      }
25
        }
26
27
    else
28
    {
29
30
      uart_puts_p(PSTR("partition open \n"));
31
32
          /* open file system */
33
          struct fat_fs_struct* fs = fat_open(partition);
34
          if(!fs)
35
          {
36
37
              uart_puts_p(PSTR("opening filesystem failed\n"));
38
39
              continue;
40
          }
41
      else
42
      {
43
        uart_puts_p(PSTR("filesystem open \n"));
44
45
46
            /* open root directory */
47
            struct fat_dir_entry_struct directory;
48
49
50
            if(fat_get_dir_entry_of_path(fs, "/test", &directory))
51
        {
52
          uart_puts_p(PSTR("fat_get_dir_entry_of_path\n"));
53
      
54
55
              struct fat_dir_struct* dd = fat_open_dir(fs, &directory);
56
              if(!dd)
57
              {
58
59
                  uart_puts_p(PSTR("opening root directory failed\n"));
60
              }
61
          else
62
          {
63
64
            uart_puts_p(PSTR("Filesystem open \n"));
65
    
66
  
67
         
68
69
70
            uart_puts("\n");
71
72
            while(fat_read_dir(dd, &directory))
73
              {
74
                    if(strcmp(directory.long_name, "test.txt") == 0)
75
                    {
76
          
77
                uart_puts("found test.txt \n");
78
                uart_puts(directory.long_name);
79
                uart_puts("\n");
80
81
                struct fat_file_struct * file = fat_open_file(fs,&directory);
82
                
83
                if(!file)
84
                {
85
                  uart_puts_p(PSTR("file error\n"));
86
                }
87
                else
88
                {
89
                  uart_puts_p(PSTR("file ok\n"));
90
91
                  char write[] = "test";
92
  
93
                  int data_len = strlen(write);
94
95
96
                  if(fat_write_file(file, (uint8_t*) write, data_len) != data_len)
97
                      {
98
                          uart_puts_p(PSTR("error writing to file\n"));
99
                    break;
100
      
101
  
102
                      }
103
                  else
104
                  {
105
                    uart_puts("file beschrieben \n");
106
                    fat_close_file (file);
107
                    break;
108
                  }
109
110
  
111
                }
112
                 
113
                break;   
114
                   }
115
              
116
117
              }
118
119
          }
120
        }
121
        
122
      }
123
       
124
    }
125
        
126
127
    break;

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Jan (Gast)


Lesenswert?

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

von Jan (Gast)


Lesenswert?

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?

von Uwe B. (boerge) Benutzerseite


Lesenswert?

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

von Uwe B. (boerge) Benutzerseite


Lesenswert?

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

von Gast (Gast)


Lesenswert?

Kurze Frage, hab ich das richtig verstanden - die SD-Karte geht nur in 
Verbindung mit externem RAM ? Geht das nicht auch ohne?

von Uwe B. (boerge) Benutzerseite


Lesenswert?

mit SRAM meine ich natürlich den internen SRAM im Mega...

von Roland R. (roland) Benutzerseite


Lesenswert?

@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

von Sucher (Gast)


Lesenswert?

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

von Torsten S. (tse)


Lesenswert?

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

von Jan (Gast)


Lesenswert?

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.

von Roland R. (roland) Benutzerseite


Lesenswert?

@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

von Sucher (Gast)


Lesenswert?

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?"

von Vladimir (Gast)


Lesenswert?

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

von Joachim (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Joachim (Gast)


Lesenswert?

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

von Dschadu (Gast)


Lesenswert?

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 :)

von geb (Gast)


Lesenswert?

@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

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Dschadu,

Les Dir mal die FAQ durch, insbesondere
    http://www.roland-riegel.de/sd-reader/faq/#faq_socketcdcl

Dann sollte es auch mit dem Schreiben funktionieren...

Gruß,
Roland

von Matze (Gast)


Angehängte Dateien:

Lesenswert?

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:
1
uint8_t sd_init();
2
void   sd_ende();
3
uint8_t sd_write(char* file, char* data, uint8_t length, uint32_t pos, uint8_t whence);
4
uint8_t sd_read(char* file, char* erg, uint8_t length, uint8_t max_length, uint32_t pos, uint8_t whence);
5
uint8_t sd_cd(char* dir);
6
uint8_t sd_deletfile(char* file);
7
uint8_t sd_creatfile(char* file);
8
uint8_t sd_creatdir(char* dir);
9
uint8_t sd_print_disk_info();
Sodass ich nur diese Methoden brauche.

Ich versuche jetzt schon seit mehr als 2 Woche etwas dergleichen zu 
machen. Klappt leider nicht.

nun gut. ich hab jetzt nochmal was anderes probiert mit dem ich mich 
abfinden könnte wenns täte :(
Diese Version habe ich angehängt. Ich hab dabei nur die main.c verändert
Zu den Fehlern:
es wird nur am Uart nur "Start" und "init" ausgegeben dies allerding 
ständig der macht also irgendwo im init teil nen reset.

Wenn ich allerdings die Schleife while(idle) -sammt Inhalt- 
auskommentiere dann initialisiert er ganz normal und gibt mir die Disk 
Info aus.

Ich hab dann mal noch verschiedene sachen ausprobiert mit if oder mit 
weniger schleifen ... jedesmal kam was anderes raus. aber nie das was 
sollte.

Diese fehler lassen darauf schließen, dass der Compiler misst macht. Und 
das gefällt mir garnicht!

Nebenbei ich benutze nen ATmega168 @ 18,432MHz
und eclipse mit AVR-plugin und WinAVR

ich bin langsam am verzweifeln und kurz davor an die Decke zu gehen.
Hat jemand ne Idee was ich falsch mach

oder Methoden wie ich sie am Anfang beschrieben hab gemacht?
Wäre sehr dankbar über Hilfe

gruß
Matze

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Thomas (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Thomas (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Lowtzow .. (lowtzow)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

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

von Pete K. (pete77)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

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

von Hannes (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Hannes (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Hannes (Gast)


Lesenswert?

herzlichen dank für den hinweis!
das mit dem brown out ist super

Viele Grüße
Franz

von Pete K. (pete77)


Angehängte Dateien:

Lesenswert?

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...

von Pete K. (pete77)


Lesenswert?

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...

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Pete K. (pete77)


Lesenswert?

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.

von Pete K. (pete77)


Angehängte Dateien:

Lesenswert?

Beim Bearbeiten kann man keine Datei anhängen.

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Pete K. (pete77)


Lesenswert?

Ein anderer Controller bringt die gleichen Ergebnisse.

Die CS-Leitung hat 1k8 Ohm gemessen vom µC Pin zum Slot. Stimmt soweit.

von Pete K. (pete77)


Angehängte Dateien:

Lesenswert?

Hier ein größeres Bild vom BRD-File.

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Torsten S. (tse)


Lesenswert?

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?

von Pete K. (pete77)


Lesenswert?

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....

von Torsten S. (tse)


Lesenswert?

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.

von Pete K. (pete77)


Lesenswert?

Der Kartenhalter ist gespiegelt (ggrrrmmmppfff), da muss ich wohl erst 
einmal eine neue Platine machen.

Vielen Dank für eure Mithilfe!

von Torsten S. (tse)


Lesenswert?

Eine Runde für alle ist nun fällig ;)

von Pete K. (pete77)


Lesenswert?


von Torsten S. (tse)


Lesenswert?

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.

von Dschadu (Gast)


Lesenswert?

Bei mir funktioniert das Programm jetzt wunderbahr, danke! :)

von Kai J. (tairon)


Lesenswert?

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?

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Kai J. (tairon)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

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

von Kai J. (tairon)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Kai,

Danke Dir für die Rückmeldung. Die Änderung wird dann in der nächsten 
sd-reader-Version enthalten sein.

Gruß,
Roland

von Hans (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Ivan H. (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Hannes Ebner (Gast)


Angehängte Dateien:

Lesenswert?

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

von Hannes Ebner (Gast)


Lesenswert?

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 :-)

von hannes ebner (Gast)


Lesenswert?

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

von Ivan H. (Gast)


Lesenswert?

@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

von Roland R. (roland) Benutzerseite


Lesenswert?

@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

von Hannes E. (hannes_ebner)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Hannes,

Vielleicht nützt es ja schon wenn Du die Karte mal neu formatierst? Das 
mit dem freien Speicherplatz macht mich stutzig.

Gruß,
Roland

von Hannes E. (hannes_ebner)


Lesenswert?

Hallo Roland,

hab´s schon ein paar mal formatiert ... vielleicht liegts am fat32 muss 
das am wochenende mal ordentlich durchprobieren.

Viele Grüße
Hannes

von Ivan H. (Gast)


Lesenswert?

Hallo Roland,

mein Problem hat sich immer noch nicht gelöst! Ich beschreibe dir nun 
meine SW: ich rufe im Main folgenden Code auf:
1
int main(void)
2
{
3
4
  
5
  UC ucBuffer[512] = {'H','a','l','l','l','o',' ','W','e','l','t'};
6
7
  UC ucRetSD = 0;
8
  
9
  ucRetSD = sd_raw_init(); //SD Karte starten
10
  
11
  if(ucRetSD)
12
  {
13
    UART_send_String_while("\nSD init OK\n");
14
    
15
  }
16
  else
17
  {
18
    UART_send_String_while("\nSD init failed\n");
19
  }
20
  
21
22
  
23
  
24
  sd_raw_write(0x0EA16A00, ucBuffer, 512);
25
  sd_raw_sync();
26
  ucBuffer[0] = 0;
27
  ucBuffer[1] = 0;
28
  ucBuffer[2] = 0;
29
  ucBuffer[3] = 0;
30
  ucBuffer[4] = 0;
31
  ucBuffer[5] = 0;
32
  ucBuffer[6] = 0;
33
  ucBuffer[7] = 0;
34
  ucBuffer[8] = 0;
35
  ucBuffer[9] = 0;
36
  sd_raw_read(0x0EA16A00, ucBuffer, 512);
37
  UART_send_Block_while(ucBuffer, 512);
38
39
40
    struct sd_raw_info disk_info;
41
     ucRetSD = sd_raw_get_info(&disk_info);
42
  
43
  lSize = disk_info.capacity /1024 /1024;
44
  sprintf(ucSizeString, "%u", lSize);
45
  
46
  UART_send_String_while("\noem:  "); UART_send_String_while(disk_info.oem);
47
  UART_send_String_while("\nprod: "); UART_send_String_while(disk_info.product);
48
  UART_send_String_while("\nsize: "); UART_send_String_while(ucSizeString);
49
  
50
  if(ucRetSD)
51
  {
52
    UART_send_String_while("\nSD info OK");
53
    
54
  }
55
  else
56
  {
57
    UART_send_String_while("\nSD info failed");
58
  }
59
  
60
  
61
62
  UART_send_String_while("\n");
63
  sd_raw_read(0x00, ucBuffer, 512);
64
  UART_send_String_while("\n");
65
  UART_send_Block_while(ucBuffer, 512);
66
  if(ucRetSD)
67
  {
68
    UART_send_String_while("\nSD read OK\n");
69
    
70
  }
71
  else
72
  {
73
    UART_send_String_while("\nSD read failed\n");
74
  }
75
  
76
}

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:
ëXMSDOS5.0

Wo liegt der Fehler?

gruss Ivan

von Werner B. (werner-b)


Lesenswert?

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.

von Ivan H. (Gast)


Lesenswert?

@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.

von stuner (Gast)


Lesenswert?

Wollte hier nur mal danke sagen. Ich hab die Library für meinen 
ATxmega32 portiert und es funktioniert wunderbar.

von Julian W. (julian-w) Benutzerseite


Lesenswert?

Hallo,
ich würde gerne eine Datei mit Variablen Namen erstellen, doch leider 
geht es nicht.
Kann mir einer helfen?
1
[...]
2
3
char tmp_name[13];
4
char* name = tmp_name;
5
name[0] = ((gps_data.tag / 10) + 0x30);
6
name[1] = ((gps_data.tag%10) + 0x30);
7
name[2] = '.';
8
name[3] = ((gps_data.monat / 10) + 0x30);
9
name[4] = ((gps_data.monat%10) + 0x30);
10
name[5] = '.';
11
name[6] = ((gps_data.jahr%2000 / 10) + 0x30);
12
name[7] = (((gps_data.jahr%2000)%10) + 0x30);
13
name[8] = '.';
14
name[9] = 't';
15
name[10] = 'x';
16
name[11] = 't';
17
name[12] = '\0';
18
19
20
static struct fat_dir_entry_struct file_entry;
21
if(!fat_create_file(dd, tmp_name, &file_entry))
22
{
23
    return 1;
24
}
25
26
[...]

von Martin J. (bluematrix) Benutzerseite


Lesenswert?

*abo

von Pete K. (pete77)


Lesenswert?

Warum schreibst Du nicht die Werte in tmp_name, wenn Du das als Variable 
übergibst?

Versuch mal: if(!fat_create_file(dd, name, &file_entry))

von Martin J. (bluematrix) Benutzerseite


Angehängte Dateien:

Lesenswert?

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.
1
if(fat_write_file(fd, (uint8_t*) sd_buffer, strlen(sd_buffer)) != strlen(sd_buffer))
2
{
3
uart1_puts("Fehler beim schreiben\n\r");
4
}                              
5
sd_raw_sync();

Problem 2:
Manchmal habe ich auch Probleme mit der Initialisierung von SD Karten.
Die Karten arbeiten 20mal problemlos. Das bedeutet ich kann die karte 
auf mein Boardstecken und beschreiben und die Daten dann per PC von der 
Karte lesen.
Und dann klappt das eine ganze Zeit lang nicht mehr. Ich kann zwar die 
karte initialisieren, die Kartininformation und filesystem auslesen, 
aber das gewünschte File nicht erzeugen oder öffnen oder bis an das 
fileende springen.
Keine Ahnung warum, ist reinzufällig.

Mein Programm findet ihr im Anhang, würde mich über jede Hilfe freuen.

Schon mal vielen Dank
Martin
Martin Junghans

von Martin J. (bluematrix) Benutzerseite


Angehängte Dateien:

Lesenswert?

hier nochmal die main.c einzeln

von Meini (Gast)


Lesenswert?

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.

von Martin J. (bluematrix) Benutzerseite


Angehängte Dateien:

Lesenswert?

schaltung ist über einen HCT125 realisiert... siehe Anhang

von Meini (Gast)


Lesenswert?

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?

von Meini (Gast)


Lesenswert?

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.

von Martin J. (bluematrix) Benutzerseite


Lesenswert?

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!?!?!?

von Martin J. (bluematrix) Benutzerseite


Lesenswert?

files öffnen geht auch... nur schreiben geht nicht.

Das geht doch gar nicht. wie kann ich nicht schreiben können wenn alles 
andere funktioniert?

von Meini (Gast)


Lesenswert?

Also wenn der Prozessor mit 5V arbeitet, hast du ein Problem.
Die SD KArten geben 3,3Volt aus und der Prozessor kann unter umständen 
nicht erkennen was logisch 1 oder 0 ist.(oder umgekehrt)

Ich sag dir was: Ich hatte ein ähnliches Problem. Ich hatte die 
Anpassung über widerstände an die SD Karten gemacht.

Alles lief einwandfrei. Nur nach mehreren Stunden schreiben auf die SD 
Karten hatte ich plötzlich das Problem, dass die Karte nicht mehr 
akzeptiert wurde.(Schreibfehler) Die Karte konnte am PC auch nicht 
gelesen oder formatiert werden. Sie war einfach defekt.
Eine andere Karte ging einwandfrei.

Der Grund lag in der mangelhaften Übertragung der Signale zur Karte.
Bei niedriger Übertragungsrate trat das Problem  nicht auf, nur bei 
höherer.

Dein Problem liegt meiner Meinung an der Spannungsanpassung von Karte zu 
Mikroprozessor.
Ich denke du solltest dir einen Level shifter suchen.
Ich kenn jetzt nur MAX3372E MAX3379 MAX3390 MAX3393E von meinen MkII 
Programmierer.
Die sind aber schwer zu bekommen.

von Martin J. (bluematrix) Benutzerseite


Lesenswert?

hat jemand schon eine fertige Schaltung für so einen Level shifter?
muss man nicht einen bidirektionalen Wandler nehmen, da ja daten in 
beide Richtungen gesendet werden?
Du hast mir nur einseite aufgelistet.

Informationen zu den Maxim Pegelwandlern gibts hier:
http://datasheets.maxim-ic.com/en/ds/MAX3372E-MAX3393E.pdf
http://www.maxim-ic.com/datasheet/index.mvp/id/3253

Danke martin

von Meini (Gast)


Lesenswert?

Hier mal ein Link zu einem Fertigen KartenModul mit Pegelanpassung.

http://www.shop.display3000.com/elektronikmodule/sd-speicherkartenplatine.html

von Martin J. (bluematrix) Benutzerseite


Angehängte Dateien:

Lesenswert?

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

von Meini (Gast)


Lesenswert?

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.

von Meini (Gast)


Lesenswert?

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)

von Meini (Gast)


Lesenswert?

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.

von Martin J. (bluematrix) Benutzerseite


Lesenswert?

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

von Ingo S. (ingo-s)


Lesenswert?

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

von holger (Gast)


Lesenswert?

>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.

von Torsten S. (tse)


Lesenswert?

> 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

von Ingo S. (ingo-s)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

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

von Tobias M. (obi)


Lesenswert?

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

von Morbit (Gast)


Lesenswert?

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.
1
int main(void) {
2
  sd_raw_init();
3
4
  struct partition_struct* partition = partition_open(sd_raw_read,
5
                            sd_raw_read_interval,
6
                            sd_raw_write,
7
                            sd_raw_write_interval,
8
                            0);
9
10
  if (!partition) {
11
    partition = partition_open(sd_raw_read,
12
                  sd_raw_read_interval,
13
                  sd_raw_write,
14
                  sd_raw_write_interval,
15
                  -1);
16
17
    if (!partition) {
18
    }
19
  }
20
  
21
  struct fat_fs_struct* fs = fat_open(partition);
22
  struct fat_dir_entry_struct directory;
23
  fat_get_dir_entry_of_path(fs, "/", &directory);
24
  struct fat_dir_struct* dd = fat_open_dir(fs, &directory);
25
26
  struct fat_dir_entry_struct file_entry;
27
  if (!fat_create_file(dd, "Test.log", &file_entry)) {
28
    //LED_RED_ON;
29
  } else {
30
    //LED_GREEN_ON;
31
  }
32
33
  /*
34
  struct fat_file_struct* fd = open_file_in_dir(fs, dd, "Track.log");
35
  if (!fd) {
36
    LED_RED_ON;
37
  } else {
38
    LED_GREEN_ON;
39
  }
40
41
  char* data = "abc";
42
  uint8_t data_len = 3;
43
  if (fat_write_file(fd, (uint8_t*) data, data_len) != data_len) {
44
    LED_RED_ON;
45
  }
46
47
  sd_raw_sync();
48
  */
49
  if (!sd_raw_sync()) {
50
    LED_RED_ON;
51
  } else {
52
    LED_GREEN_ON;
53
  }
54
  delay_s(5);
55
  LED_GREEN_OFF;
56
  LED_RED_OFF;
57
//  fat_close_file(fd);
58
  fat_close_dir(dd);
59
  fat_close(fs);
60
  partition_close(partition);
61
62
  return 0;
63
}

von Werner F. (frewer)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Werner,

Schau bitte mal in die FAQ auf meiner Homepage:
  http://www.roland-riegel.de/sd-reader/faq/#faq_writefails
  http://www.roland-riegel.de/sd-reader/faq/#faq_socketcdcl

Gruß,
Roland

von Werner F. (frewer)


Lesenswert?

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???

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von frewer (Gast)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Werner F. (frewer)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Werner F. (frewer)


Lesenswert?

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

von Werner F. (frewer)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Werner F. (frewer)


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

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

von Martin (Gast)


Lesenswert?

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

von Stefan W. (stepw)


Lesenswert?

eine kleine Frage, kann man die SD-Karte an beliebigen Ports anschließen 
oder muß es immer Hardware-MOSI/MISO/SCK sein?

von Martin (Gast)


Lesenswert?

vom Programm wird nur der Hardware SPI unterstützt...
Software SPI wäre aber auch möglich, muss du dann nur selber 
implementieren.

von Stefan W. (stepw)


Lesenswert?

danke für die info - schade, da wüßte ich jetzt nicht wie das gehen 
sollte.

von Martin (Gast)


Lesenswert?

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.
1
//##########################################################################################
2
uint8_t file_getLine(uint16_t lineNr,char* zielbuffer)// anzahl Zeilen aktuelles file
3
{ // Rückgabe der Zeilenlänge
4
  // maximale Zeilenlänge von 40 Zeichen
5
  
6
  if(fd)
7
  {
8
    if (lineNr < 1 ) {return 0;}
9
    
10
    uint16_t   counterLines  =0;
11
    int32_t   pos_after_last_enter   = 0;
12
    uint8_t   arbeitsbuffer[40];  
13
    uint8_t    count;
14
15
    //########## Anfang der n-ten Zeile suchen und position in "pos_after_last_enter" zurückgeben
16
    //########## es werden alle '\n' gezählt bis die Anfangsposition der gesuchten Zeile gefunden ist
17
        
18
    while(counterLines < lineNr-1)
19
      {
20
      if(!fat_seek_file(fd, &pos_after_last_enter, FAT_SEEK_SET)) {/* error*/}
21
      
22
      count = fat_read_file(fd, arbeitsbuffer, 40);
23
      for(intptr_t i = 0; i < count; ++i)
24
        {
25
        if(arbeitsbuffer[i] == '\n')  
26
          {
27
          counterLines++;
28
          pos_after_last_enter+=i+1;// Zeiger auf Zeichen nach dem letzten Enter
29
          break;
30
          }
31
        }
32
      }
33
    
34
    //########## Daten ab der gefundenen Position auslesen und in Zielbuffer schreiben    
35
    if(!fat_seek_file(fd, &pos_after_last_enter, FAT_SEEK_SET)) {/* error*/}
36
    count = fat_read_file(fd, arbeitsbuffer, 40);
37
    
38
    for(intptr_t i=0; i<count; ++i)
39
      {
40
      zielbuffer[i] = arbeitsbuffer[i];      
41
      if(arbeitsbuffer[i] == '\n')  
42
        {
43
        zielbuffer[i+1] = 0;
44
        return i; // return Zeilenlänge
45
        }
46
      }
47
  }
48
  return 0;
49
}

von nlsgs (Gast)


Lesenswert?

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.

von Werner B. (werner-b)


Lesenswert?


von Steffen (Gast)


Lesenswert?

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.
1
void play_sound(const char *file_name, struct fat_fs_struct* fs, struct fat_dir_struct* dd)
2
{
3
  int32_t bytesRead = 0;
4
  int32_t totalBytesRead = 0;
5
  int countVar;
6
        uint8_t songbuffer[32];
7
        struct fat_file_struct* fd;
8
9
  fd = open_file_in_dir(fs, dd, file_name);   
10
        bytesRead = fat_read_file(fd, songbuffer, 32);
11
  
12
        while(bytesRead > 0)  
13
  {
14
    totalBytesRead+=bytesRead;
15
    fat_close_file(fd);
16
    unselect_card();
17
18
// hier steht ein Routine zum senden des Buffer-Inhaltes an den Decoder
19
...
20
//
21
                select_card();
22
                fd = open_file_in_dir(fs, dd, file_name);
23
          fat_seek_file(fd,&totalBytesRead,FAT_SEEK_SET); 
24
    bytesRead = fat_read_file(fd, songbuffer, 32);
25
   }
26
    fat_close_file(fd);
27
}

Hoffe, mir kann geholfen werden.

Gruß
Steffen

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Steffen (Gast)


Lesenswert?

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

von Steffen (Gast)


Lesenswert?

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

von Steffen (Gast)


Lesenswert?

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.

von Steffen (Gast)


Lesenswert?

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

von holger (Gast)


Lesenswert?

>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.
1
void play_sound(const char *file_name, struct fat_fs_struct* fs, struct fat_dir_struct* dd)
2
{
3
  int32_t bytesRead = 0;
4
  int countVar;
5
        uint8_t songbuffer[32];
6
        struct fat_file_struct* fd;
7
8
  fd = open_file_in_dir(fs, dd, file_name);   
9
  if(fd)
10
   {
11
    do
12
    {
13
     bytesRead = fat_read_file(fd, songbuffer, 32);
14
15
// hier steht ein Routine zum senden des Buffer-Inhaltes an den Decoder
16
...
17
//
18
    } while(bytesRead > 0)  
19
    fat_close_file(fd);
20
  }
21
}

von holger (Gast)


Lesenswert?

Nachtrag: kleine Verbesserung;)
1
void play_sound(const char *file_name, struct fat_fs_struct* fs, struct fat_dir_struct* dd)
2
{
3
  int32_t bytesRead = 0;
4
  int countVar;
5
        uint8_t songbuffer[32];
6
        struct fat_file_struct* fd;
7
8
  fd = open_file_in_dir(fs, dd, file_name);   
9
  if(fd)
10
   {
11
    do
12
    {
13
     bytesRead = fat_read_file(fd, songbuffer, 32);
14
     if(bytesRead > 0)
15
     {
16
// hier steht ein Routine zum senden des Buffer-Inhaltes an den Decoder
17
...
18
//
19
     }
20
    } while(bytesRead > 0)  
21
    fat_close_file(fd);
22
  }
23
}

von Roland R. (roland) Benutzerseite


Lesenswert?

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

von Steffen (Gast)


Lesenswert?

Hallo zusammen!

An der Stelle wollte ich mich einfach nochmal für die schnelle Hilfe 
bedanken, die mir zuteil wurde. :)

Gruß
Steffen

von Daniel (Gast)


Lesenswert?

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

von Frank H. (gowi)


Lesenswert?

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:
1
int main()
2
{
3
        /* setup sd card slot */
4
        if(!sd_raw_init())
5
        {
6
#if DEBUG
7
            uart_puts_p(PSTR("MMC/SD initialization failed\n"));
8
#endif
9
            continue;
10
        }
11
12
        /* open first partition */
13
        struct partition_struct* partition = partition_open(sd_raw_read,                                              sd_raw_read_interval,
14
                                                            0,
15
                                                            0,
16
                                                            0
17
                                                           );
18
19
        if(!partition)
20
        {
21
            /* If the partition did not open, assume the storage device
22
             * is a "superfloppy", i.e. has no MBR.
23
             */
24
            partition = partition_open(sd_raw_read,
25
                                       sd_raw_read_interval,
26
                                       0,
27
                                       0,
28
                                       -1
29
                                      );
30
            if(!partition)
31
            {
32
#if DEBUG
33
                uart_puts_p(PSTR("opening partition failed\n"));
34
#endif
35
                continue;
36
            }
37
        }
38
39
        /* open file system */
40
        struct fat_fs_struct* fs = fat_open(partition);
41
        if(!fs)
42
        {
43
#if DEBUG
44
            uart_puts_p(PSTR("opening filesystem failed\n"));
45
#endif
46
            continue;
47
        }
48
49
        /* open root directory */
50
        struct fat_dir_entry_struct directory;
51
        fat_get_dir_entry_of_path(fs, "/", &directory);
52
53
        struct fat_dir_struct* dd = fat_open_dir(fs, &directory);
54
        if(!dd)
55
        {
56
#if DEBUG
57
            uart_puts_p(PSTR("opening root directory failed\n"));
58
#endif
59
            continue;
60
        }
61
        
62
  struct fat_dir_entry_struct fdes;
63
  uint8_t ret_value;
64
  struct fat_file_struct* ffs;
65
  ret_value = fat_create_file(dd, "ABDEEFGH.TXT", &fdes);
66
  if (ret_value == 1) {
67
    ffs = fat_open_file(fs, &fdes);
68
    if (!ffs) {
69
      uart_puts_p("a");
70
    }
71
    fat_write_file(ffs, "Hello World", 12);
72
    fat_close_file(ffs);
73
    /* close directory */
74
    fat_close_dir(dd);
75
    /* close file system */
76
    fat_close(fs);
77
    /* close partition */
78
    partition_close(partition);
79
    while (1) {}
80
}

von Torsten S. (tse)


Lesenswert?

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.

von Martin (Gast)


Lesenswert?

Hallo,
ich versuche mich gerade am Erzeugen einer Datei und komme dabei nicht 
weiter, mein Code sieht so aus:
1
int connect_sd(void)
2
{
3
  struct partition_struct* partition;
4
  struct fat_dir_struct* dd;
5
  struct fat_fs_struct* fs;
6
  
7
  if(!sd_initiated)
8
  {
9
    if(!sd_raw_init())
10
    {
11
      uart_puts("MMC/SD initialization failed\n");
12
    }
13
    else
14
    {
15
      sd_initiated=1;
16
      uart_puts("MMC/SD initialization successful\n");
17
    }
18
  }
19
  if(sd_initiated)
20
  {
21
    struct partition_struct* partition = partition_open(  sd_raw_read,
22
    sd_raw_read_interval,
23
    sd_raw_write,
24
    sd_raw_write_interval,
25
    0
26
    );
27
    if(!partition)
28
    {
29
      partition = partition_open(sd_raw_read,
30
      sd_raw_read_interval,
31
      sd_raw_write,
32
      sd_raw_write_interval,
33
      -1
34
      );
35
      if(!partition)
36
      {
37
        uart_puts("opening partition failed\n");
38
      }
39
    }
40
    if(partition!=0)
41
    {
42
      sd_partitioned = 1;
43
      uart_puts("partition found\n");
44
      fs = fat_open(partition);
45
      if(!fs)
46
      {
47
        uart_puts("opening filesystem failed\n");
48
      }
49
      struct fat_dir_entry_struct directory;
50
      fat_get_dir_entry_of_path(fs, "/", &directory);
51
      dd = fat_open_dir(fs, &directory);
52
      if(!dd)
53
      {
54
        uart_puts("opening root directory failed\n");
55
      }
56
      else
57
      {
58
        uart_puts("opening root directory successful\n");
59
        sd_root=1;
60
      }
61
    }
62
    if(sd_root!=0)
63
    {
64
      struct fat_dir_entry_struct* fd;
65
      struct fat_file_struct* ffs;
66
      if(fat_create_file(dd,"BLABLA.TXT",&fd)!=0)
67
      {
68
        ffs = fat_open_file(fs,&fd);
69
        fat_write_file(ffs,"teststring",11);
70
      }
71
      else
72
      {
73
        uart_puts("failed to create file\n");
74
      }
75
      fat_close(fs);
76
      partition_close(partition);
77
    }
78
  }
79
  return sd_root;
80
}
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

von Martin (Gast)


Lesenswert?

Am Schluss muss es natürlich
1
if(sd_root!=0)
2
    {
3
      struct fat_dir_entry_struct* fd;
4
      struct fat_file_struct* ffs;
5
      ffs = fat_create_file(dd,"BLABLA.TXT",&fd);
6
      if(ffs!=0)
7
      {
8
        ffs = fat_open_file(fs,&fd);
9
        fat_write_file(ffs,"teststring",11);
10
      }
11
      else
12
      {
13
        uart_puts("failed to create file\n");
14
      }
15
      fat_close(fs);
16
      partition_close(partition);
17
    }
 heissen!

von Martin (Gast)


Lesenswert?

Bekomme jetzt war "writing successfull", die Datei "TEST.TXT" bleibt 
aber leer. Woran könnte das liegen?
1
if(sd_root!=0)
2
    {
3
      struct fat_file_struct* fd = open_file_in_dir(fs, dd, "TEST.TXT");
4
      if(!fd)
5
      {
6
        uart_puts("could not open test.txt\n");
7
      }
8
      else
9
      {
10
        fat_write_file(fd,"testzeile",15);
11
        sd_raw_sync();
12
        uart_puts("writing sucessfull\n");
13
      }
14
      
15
      fat_close(fs);
16
      partition_close(partition);
17
    }

von Martin (Gast)


Lesenswert?

Habe es nun gelöst, der Fehler lag im Schreibschutz, hatte das im 
config-file nicht richtig angepasst. Ansonsten danke für die super Bib!

von Dirk B. (garag)


Lesenswert?

Martin schrieb:
>
1
if(sd_root!=0)
2
>     {
3
>       struct fat_dir_entry_struct* fd;
4
>       struct fat_file_struct* ffs;
5
>       ffs = fat_create_file(dd,"BLABLA.TXT",&fd);
6
>       if(ffs!=0)
7
>       {
8
>         ffs = fat_open_file(fs,&fd);
9
>         fat_write_file(ffs,"teststring",11);
10
>       }
11
>       else
12
>       {
13
>         uart_puts("failed to create file\n");
14
>       }
15
>       fat_close(fs);
16
>       partition_close(partition);
17
>     }

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)?
1
if(sd_root!=0)
2
{
3
    struct fat_dir_entry_struct fd;
4
    struct fat_file_struct* ffs;
5
    ffs = fat_create_file(dd,"BLABLA.TXT",&fd);

von Sven W. (sven_w18)


Lesenswert?

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?

1
uint8_t find_file_in_dir(struct fat16_fs_struct* fs, struct fat16_dir_struct* dd, const char* name, struct fat16_dir_entry_struct* dir_entry)
2
{
3
    while(fat16_read_dir(dd, dir_entry))
4
    {
5
        if(strcasecmp(dir_entry->long_name, name) == 0)
6
        {
7
            fat16_reset_dir(dd);
8
            return 1;
9
        }
10
    }
11
12
    return 0;
13
}
14
15
//***************************************************************
16
17
struct fat16_file_struct* open_file_in_dir(struct fat16_fs_struct* fs, struct fat16_dir_struct* dd, const char* name)
18
{
19
    struct fat16_dir_entry_struct file_entry;
20
    if(!find_file_in_dir(fs, dd, name, &file_entry))
21
        return 0;
22
23
    return fat16_open_file(fs, &file_entry);
24
}

von ruepel (Gast)


Lesenswert?

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

Beitrag #5847275 wurde von einem Moderator gelöscht.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.