mikrocontroller.net

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


Autor: Roland Riegel (roland) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Senf (Gast)
Datum:

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

Autor: André Kronfeldt (freakazoid)
Datum:

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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: SuperUser (Gast)
Datum:

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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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 :)

Autor: Roland Riegel (roland) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Autor: Fabian (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: The Engineer (the_engineer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
*abo

Autor: Lupin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
die 3.3v stromversorgung hast du ja ganz elegant gelöst :)

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Fabian (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ?

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Lupin (Gast)
Datum:

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

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
SD-Karten bis 25 MHz.

Autor: Pete (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@roland
Wo hast Du denn den Kartenslot her ?

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Lupin (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: m@u (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Lupin (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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? :)

Autor: Fly (Gast)
Datum:

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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Tobias Gärtner (tobster)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
*abo

Autor: Peter Baumann (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Gernot Frisch (gernotfrisch)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Gernot Frisch (gernotfrisch)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Roland Riegel (roland) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Malte Ibs (maltomat)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Malte Ibs (maltomat)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Roland,

ok, alles klar, ich hatte die alte Version.

Danke
Malte

Autor: Malte Ibs (maltomat)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: T.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: T.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Malte Ibs (maltomat)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Malte Ibs (maltomat)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Malte Ibs (maltomat)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Malte Ibs (maltomat)
Datum:
Angehängte Dateien:

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

Autor: Malte Ibs (maltomat)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Malte Ibs (maltomat)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: neuer (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Avr Nix (avrnix) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
abo

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Dirk Schlage (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Malte Ibs (maltomat)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Dirk Schlage (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Malte Ibs (maltomat)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Der Techniker (_techniker_)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Einfach Geil! :-D

abo

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Malte Ibs (maltomat)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Wolfram (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Ssss Ssssss (sssssss)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Wolfram (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Wolfram (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Wolfram (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Roland Riegel (roland) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Wolfram (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Wolfram (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Roland:
Ich habe zumindest das eine Dokument im Netz gefunden:
http://www.walrus.com/~raphael/pdf/FatFormat.pdf#s...

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Uwe (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Wirus! (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Malte Ibs (maltomat)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Simon K. (simon) Benutzerseite
Datum:

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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Malte Ibs (maltomat)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: T.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter bb (Gast)
Datum:

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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter bb (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Peter bb (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Thorsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Malte Ibs (maltomat)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Thorsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: T.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Thorsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Thorsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: T.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: T.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Malte Ibs (maltomat)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Thorsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: T.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Malte Ibs (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Malte Ibs (maltomat)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Uwe (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Malte Ibs (maltomat)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Malte Ibs (maltomat)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Malte Ibs (maltomat)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Reinhold Pieper (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Reinhold Pieper (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Reinhold Pieper (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Pete (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ...

Autor: Pete (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Reinhold Pieper (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Reinhold Pieper (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: T.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Pete (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe die gleichen Probleme :-(

Autor: Pete (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ?

Autor: T.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Avr Nix (avrnix) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Pete (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: T.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Pete (Gast)
Datum:

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

Autor: Malte Ibs (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Pete (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Uwe (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: T.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Pete (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Torsten:
Hast Du Deine Karte wieder reaktieren können ?

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

Autor: Lars (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Sven Scholz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Nik Bamert (nikbamert)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Holger Milz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: T.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Funkamateur1 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Pete (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ?

Autor: Adrian (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: T.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Pete (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Pete (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 :-)

Autor: emil (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Hauke Radtki (Gast)
Datum:

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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: emil (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Roland Riegel (roland) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.







Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke, klappt jetzt.

Super!
M.

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: M. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Der versprochene Anhang

M.

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Pete (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Pete (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Mille (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Mille (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

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

Autor: jeremy (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Dirk Meyer (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Dirk Meyer (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Übrigens gute Meldung bezüglich FAT (zumindest in D):

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

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist Rolands Server down ? Ich bekomme keine Verbindung.

Autor: Mille (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Roland,

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

Gruß
Mille

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, wieder online...

:-))
Roland

Autor: Mitrofanow (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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ß.

Autor: Michael U. (tolle)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Roland,

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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Michael U. (tolle)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Michael U. (tolle)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Hansl (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: (geloescht) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
(Dieser Beitrag wurde geloescht)

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: (geloescht) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
(Dieser Beitrag wurde geloescht)

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Werner B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wegen SD formatieren:

Gibts bei Panasonic

http://panasonic.jp/support/audio/sd/download/sd_f...

Autor: (geloescht) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
(Dieser Beitrag wurde geloescht)

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: (geloescht) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
(Dieser Beitrag wurde geloescht)

Autor: T.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Michael Odenwald (odiwan)
Datum:

Bewertung
0 lesenswert
nicht 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:
#elif defined(__AVR_ATmega64__) || \
      defined(__AVR_ATmega128__)
  /* Attention: all pins must be defined for correct work */
    #define configure_pin_mosi() DDRB |= (1 << PB2)
    #define configure_pin_sck() DDRB |= (1 << PB1)
    #define configure_pin_ss() DDRB |= (1 << PB0)
    #define configure_pin_miso() DDRB &= ~(1 << PB3)

  #define select_card() *pSPI_CS &= ~(1 << SPIP4)
  #define unselect_card() *pSPI_CS |= (1 << SPIP4)
#else

Zu JTAG kann ich leider nichts sagen ich benutze nur den ISP Anschluss.

Tschau
Michael

Autor: Michael Odenwald (odiwan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

@Guido: Wieder mal zu schnell abgesendet.

Der Code geht ja noch weiter:
#elif defined(__AVR_ATmega64__) || \
      defined(__AVR_ATmega128__)
  /* Attention: all pins must be defined for correct work */
    #define configure_pin_mosi() DDRB |= (1 << PB2)
    #define configure_pin_sck() DDRB |= (1 << PB1)
    #define configure_pin_ss() DDRB |= (1 << PB0)
    #define configure_pin_miso() DDRB &= ~(1 << PB3)

  #define select_card() *pSPI_CS &= ~(1 << SPIP4)
  #define unselect_card() *pSPI_CS |= (1 << SPIP4)
#else
    #error "no sd/mmc pin mapping available!"
#endif

#define configure_pin_available()  DDRB &= ~(1 << PB7), PORTB |= (1<<PB7)    /* internen Pull-Up an PB7 aktivieren */
#define configure_pin_locked()  DDRB &= ~(1 << PB6), PORTB |= (1<<PB6)    /* internen Pull-Up an PB6 aktivieren */

#define get_pin_available() ((PINB >> PB7) & 0x01)
#define get_pin_locked() ((PINB >> PB6) & 0x01)

Der Pin available und locked funktionieren auf dem Arthernet auch.

Tschau
Michael

Autor: (geloescht) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
(Dieser Beitrag wurde geloescht)

Autor: Roland Riegel (roland) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: (geloescht) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
(Dieser Beitrag wurde geloescht)

Autor: T.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> was nehm ich da für ein Programm unter Windows?

... das gleichnamige. ;)

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

Torsten

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: (geloescht) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
(Dieser Beitrag wurde geloescht)

Autor: T.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: T.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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


Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: T.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Matthias (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Autor: T.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Matthias (Gast)
Datum:

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

Autor: Günther Frings (taraquedo)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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!

Autor: T.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: stefan richter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Joachim (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Roland Riegel (roland) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Roland Riegel (roland) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: (geloescht) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
(Dieser Beitrag wurde geloescht)

Autor: (geloescht) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
(Dieser Beitrag wurde geloescht)

Autor: taraquedo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: August (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Slater (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Hansl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo,

ich hab grad laut anleitung von ulrich radigs webseite ein
brotbrett bestueckt.

http://www.ulrichradig.de/site/atmel/avr_mmcsd/gfx...

der aufbau ist:

ein stk500 mit atmega16 und 16MhZ quarz (laeuft).

die +5V beziehe ich vom VTG anschluss an portB.

sollten da beim mmc anschluss nach den 2 dioden nicht um die 3.7V
zu messen sein? bei mir ist es davor: 4.96V und nach den 2 1N418 4.32V.

jemand ne idee wo ich mich verbastelt haben koennte?

mfg
 Hansl

Autor: Hansl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
btw. mit 4 dioden komm ich auf 3.7V

gibts unterschiedliche 1N4148er ?

Autor: jemand (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Hansl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
jemand: merci, habs eben nachgemessen. stimmt.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 :(

Autor: Hansl (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: T.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Hansl (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Joachim (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Hansl (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Wolfgang (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Joachim (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Hansl (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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





Autor: Hansl (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Werner B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: Hansl (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ;)

Autor: Joachim (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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



Autor: Hansl (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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


Autor: Joachim (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Hansl (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Autor: Hansl (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Hansl (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Joachim (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Hansl (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Hansl (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
....

Autor: Joachim (Gast)
Datum:

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

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

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

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

Joachim

Autor: Hansl (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Joachim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tja, dann bin ich auch am Ende meiner Weisheit.
Sorry.

Joachim

Autor: Richard Brose (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Andreas W. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

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

Bewertung
0 lesenswert
nicht 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).

Autor: Joachim (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
/* set block size to 512 bytes */
    if(sd_raw_send_command_r1(CMD_SET_BLOCKLEN, 512))
Wenn Du die Startadresse nicht auf den Sektorstart legst, jedoch eine 
Blockgröße von 512 eingestellt ist, kommt es zu einem Sektorüberlauf
(Read Block Misalignment).

> Frage: hat jemand eine Idee ob das mit dem Offset an der SD liegt?
Nein.
Der Offset ist eine Eigenschaft des FAT-Filesystems.
Der MBR liegt nie gleich am Anfang der Karte.

In der Partitionstabelle ist der Offset angegeben, z.B.
"Sectors preceding partition 1: 237"
Der MBR liegt also in diesem Fall bei 0x1DA00



Joachim

Autor: Andreas W. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.