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


von MarkusW (Gast)


Lesenswert?

Hallo, ich bin´s nochmal...

komme gerade nicht so richtig weiter.

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

Bis zu der "---------" kommt er, aber in der device_read-Funktion kommt 
er nicht mehr an. Wenn ich das richtig sehe, müsste er ja in

struct partition_struct* partition_open(...

ankommen. Kommt er aber nicht. Bin etwas ratlos gerade. Mit eine 
8MB-Karte läuft alles.

Gruß
Markus

von MarkusW (Gast)


Lesenswert?

So, es geht!

Hab allerdings einen andere "Formatter" benutzt (nicht Windows, sondern 
"SD Formatter 2.0" von Panasonic(?)).

Damit geht´s ohne Probleme und auch Windows kann die Dateien einwandfrei 
lesen.

Irgendeine Idee?

von niketchana (Gast)


Lesenswert?

Hallo Zusammen,
ich benutze die USART Schnittstelle vom AT90USB1287 in SPI Master Mode, 
um DAB(digital audio broadcast) Daten auf der SD-Karte zu speichern.Beim 
Debuggen wird in der Funktion "struct fat16_fs_struct* fs = 
fat16_open(partition);" die folgende Zeile nicht richtig ausgeführt 
"if(!fat16_read_header(fs))".In dieser Funktion ruft die 
Zeile:"if(!partition->device_read(partition_offset + 0x0b, buffer, 
sizeof(buffer)))" die Funktion "uint8_t sd_raw_read(uint32_t offset, 
uint8_t* buffer, uint16_t length)" auf.In dieser Funktion(sd_raw_read) 
hängt das Programm an der folgenden Stelle:

 /* wait for data block (start byte 0xfe) */
            while(sd_raw_rec_byte() != 0xfe);

Das ist die kritische Stelle.Die Funktion sd_raw_rec_byte() sieht so 
aus:

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

    return SPDR;*/

  // Send dummy data for receiving some.
  UDR1 = 0xff;

  // Wait for empty transmit buffer.
  do {} while( (UCSR1A & (1<<UDRE1)) == 0 );

  // Wait for transfer to complete and return received value.
  do {} while( (UCSR1A & (1<<RXC1)) == 0 );

  return UDR1;
}

Weiss jemand woran es liegt, dass das Programm an dieser Stelle hängen 
bleibt? Da ich USART in Master SPI Mode benutze habe ich einige Stellen 
in den Datei im Anhang verändert. Vielleicht hift es bei der 
Fehlersuche.
Ich bedanke mich im voraus für Ihre Hilfe.
Gruss
niketchana

von niketchana (Gast)


Lesenswert?

Hallo,
jetzt geht´s. Das war ein Problem der Formatierung.Anscheinend 
formatiert Window mit FAT12.Ich habe die Karte mit dem "SD Formatter 
2.0.0.3 von Panasonic" formatiert und schon geht alles.
niketchana

von Gast (Gast)


Lesenswert?

Hallo,
hat sich in diesem Zusammenhang schon mal jemand mit Gnu unzip 
beschäftigt? Ich hab das Problem das ich eine Gnu gezippte Datei auf 
einer SD-Karte auslesen und gleichzeitig entpacken will.
Danke

von Roland R. (roland) Benutzerseite


Lesenswert?

Nein, ich zumindest nicht. Warum ist die Datei denn gepackt, bzw. muss 
sie das denn sein? Die Karten sind doch eh groß genug.

Ich würde in diesem Zusammenhang auch erst mal mit zlib experimentieren, 
das sollte besser portierbar sein. Habe allerdings keine Ahnung, wieviel 
Flash der Algorithmus belegen würde. Es gibt jedoch schon ein Beispiel 
namens "minizip", das den ZIP-Header interpretiert. Alternativ das 
GZ-Format verwenden, das ist einfacher.

Gruß,
Roland

von Gast (Gast)


Lesenswert?

Das Flash im Prozessor leider nicht.
Ich brauche eh das Gnu Format.

Ich hab mich mal bei der Busybox umgeschaut.
Vielleicht komme ich damit weiter.

Danke, für die Antwort

von pito (Gast)


Lesenswert?

Hi gents,
let me ask you kindly following: I am running the latest sdreader demo 
and when writing a text file to the 512MB SD card (atmega32, 11MHz, 115k 
8n1)via the write command (realterm terminal - dump file to port) the 
writing speed is aprox 400-500byte/sec. Is this a typical speed or is 
there something wrong with my setup?
Thanks, pito.

von Roland R. (roland) Benutzerseite


Lesenswert?

The sd-reader text console accessible via UART is not meant to be used 
as a data interface during normal operation, the same applies to the 
circuit itself. It is for debugging and test purposes only.

To achieve proper speed, integrate the circuit and the 
sd_raw/partition/fat16 code into your application. Depending on the 
configuration and the size of the buffers used, several dozens of 
kBytes/sec are possible.

Greetings,
Roland

von pito (Gast)


Lesenswert?

Hi Roland,
thanks! I do consider your test code as very useful for us - beginners, 
to play with the sdcard and FAT16.. and for diagnostic purposes too.. 
I've tried several other implementations, however this one is my 
favorite as there is the test console offered!

Let me ask you kindly whether would be possible for you (or somebody 
from community who understand the implementation well) to insert a 
simple command (e.g.copy) into the sdreader test console for testing the 
copying of files e.g.:

copy file1 file2 (files of any size)

in the actual directory you moved in via cd command. It will be very 
useful for experimenting with setups/buffers etc and testing the cards.

Thanks a lot,
Pito

von Roland R. (roland) Benutzerseite


Lesenswert?

No, I will not implement this.
You can do this yourself, it's quite simple. Use fat16_open_file(), 
fat16_read_file(), fat16_close_file() for the file which to read, and 
fat16_create_file(), fat16_open_file(), (fat16_resize_file(),) 
fat16_write_file(), fat16_close_file() for the file to write.

See
    http://www.roland-riegel.de/sd-reader/doc/group__fat16__file.html
for the documentation of the FAT16 file handling.

Greetings,
Roland

von hihi (Gast)


Lesenswert?

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

von pito (Gast)


Lesenswert?

Ok, alles klar.. Ich dachte nur - fals man schon das ganze Geschichte 
drin in einen email steckt, wird das schon vielleicht bischen 
einfacherer und schneller das Code in den sdreader implementieren zu 
koennen (:-). Aber Ich verstehe ganz gut (da ich auch von Arbeit solche 
miesse triks kenne) dass man schon andere Sachen zu tun haette.. Ich bin 
auch nicht besonders geil die Sachen die schon einwandfrei laufen nur so 
mirnix dirnix anfassen zu muessen (auch wenn jemand solche bereitschaft 
"Kundenorientation" nennt). Nun - was mir in den "debug code" fehlt ist 
eine Moeglichkeit die reine Transfergeschwindichkeit unter bestimmten 
Bedinungen einfach zu beobachten. Und dafuer is der "copy" Befehl sehr 
gut geeignet, meine Ich. Man braucht nix anders. Niemand bietet Euch 
(die Experten) ein MMC DOS zu schreiben..
Gruss,
Pito

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

Hallo allerseits,

Heute nach längerer Pause mal wieder ein Update.

Zwei wesentliche Features sind dazugekommen:
- Unterstützung für SDHC-Karten.
- Unterstützung für FAT32.

Insgesamt heißt dass, das jetzt auch Karten mit mehr als 2GB genutzt 
werden können. Da die Neuerungen einiges an Flash mehr brauchen ist für 
die Beispielanwendung mindestens ein ATmega328 erforderlich. Da ich 
diesen noch nicht habe (getestet wurde das ganze mit mega-eth), sind die 
neuen Features standardmäßig abgeschaltet. Zum Einschalten SD_RAW_SDHC 
in sd_raw_config.h auf 1 setzen.

Wie immer ist die Doku im ZIP enthalten, findet sich zusammen mit einem 
Patch zur vorhergehenden Version aber auch auf der Homepage unter
  http://www.roland-riegel.de/sd-reader/

Viele Grüße,
Roland

von Torsten S. (tse)


Lesenswert?

Hallo Roland,

Das sind sehr gute Neuigkeiten. Danke dass Du uns Deinen Code zur 
Verfügung stellst!

Mehr Flash ist (bei mir) kein Problem. Wie sieht es aber mit dem SRam 
aus - wird mehr gebraucht oder bleibt alles beim alten?

Torsten

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Torsten!

Die Datenstrukturen haben sich nicht wesentlich geändert, allerdings 
sind einige Elemente größer geworden, da mit FAT32 die Clusternummern 
und mit SDHC die Offsetadressen breiter werden. Dies ist mit den 
Typedefs cluster_t bzw. offset_t geregelt.

Ein kleiner Überblick:
- geöffnetes Dateisystem: +12 Bytes
- directory entry: +6 Bytes
- geöffnete Datei: +12 Bytes (inkl. dir entry)
- geöffnetes Verzeichnis: +8 Bytes (inkl. dir entry)

Beim Dateisystem könnte man eventuell noch vier Bytes rausholen, 
insgesamt sind die Zuwächse aber eher human.

Viele Grüße,
Roland

von Torsten S. (tse)


Lesenswert?

Hallo Roland,

Danke für den kurzen Überblick. Der Mehrverbrauch an SRam ist wirklich 
zu verschmerzen wenn man sich vor Augen hält das nun Fat32 und Sdhc 
unterstützt werden. Bei der nächsten Gelegenheit werde ich alles mal 
testen und Dir ein Feedback geben.

"Keep up your good work!"

Torsten

von Roland R. (roland) Benutzerseite


Lesenswert?

Ok, bin gespannt ob es auf Anhieb funktioniert.

Nochmal zum RAM-Verbrauch: Der Stack wird auch etwas größer sein als 
zuvor, da mit den breiteren Datentypen natürlich gearbeitet werden muss. 
Wieviel das genau ausmacht, kann ich auf Anhieb aber nicht sagen.

Gruß,
Roland

von Werner B. (werner-b)


Lesenswert?

@Roland Riegel

Hallo Roland,

ein kleines Problem.

Ich verwende deine FAT (sd-reader_source_20081121.zip) für meinen AVR 
Webserver (basiert auf deinem ;-)).
Das Problem ist...

Bei Datei- bzw. Verzeichnisnamen welche in das 8.3 Format passen wird 
der Name offenbar immer in Großbuchstaben gesucht/angezeigt, obwohl 
diese unter Windoze oder Linux mit Kleinbuchstaben auf die SD kopiert 
wurden (und auf diesen OSs auch so angzeigt werden).
Da funktionieren natürlich die Links auf dem Webserver nicht mehr :-(

Hast du ein Idee wo ich etwas ändern muss?

Danke schon mal

Werner

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

von Werner B. (werner-b)


Lesenswert?

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

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

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Werner,

Bei 8.3-Namen schreiben die Betriebssysteme keine LFN-Namen ins 
Verzeichnis (im Unterschied übrigens zum sd-reader). Die 8.3-Namen 
werden immer in Großbuchstaben abgespeichert.
Soweit ich mich erinnere gibt es aber ein paar Bits, die angeben, ob 
diese Namen als "GROSS", "klein" oder "Gemischt" interpretiert werden 
sollen. Ich werde nochmal danach suchen und schauen, ob und wie einfach 
man das implementieren kann.

Gruß,
Roland

von Werner B. (werner-b)


Lesenswert?

Hallo Roland,

als "Workaround" abe ich eben die betreffenden strcmp in strcasecmp 
geändert.
Funktioniert soweit, sollte aber nicht die engültige Lösung sein.

Danke nochmal für den wirklich sauber und glasklar strukturierten Code.
Endlich mal jemand der seinen Quelltext so formatiert wie ich ;-)
fühle mich darin "Zuhause".

Gruß,
Werner

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

Servus Werner,

Freut mich wenn Dir mein Code gefällt.

Probiere mal den angehängten Patch. Bei mir zeigt er damit in Tests die 
korrekte Groß-/Kleinschreibung an.

Viele Grüße,
Roland

von Werner B. (werner-b)


Lesenswert?

Hallo Roland,

klappt hervorragend.

Danke!

Werner

von Torsten S. (tse)


Lesenswert?

Roland

> klappt hervorragend.

Sieht so aus als wenn eine neue Version fällig ist. ;) Bin selbst noch 
nicht zum testen gekommen, könnte noch eine Weile dauern..

Torsten

von Roland R. (roland) Benutzerseite


Lesenswert?

@Werner

Ok schön, habe die Änderung übernommen, sie wird dann in der nächsten 
Version enthalten sein.

@Torsten

Nö, deswegen mache ich nicht gleich ne neue Version. Es tritt ja nur bei 
8.3-Namen auf und auch nur, wenn die Dateien auf dem PC erzeugt werden. 
Und wen es doch stört, der kann ja den Patch von oben verwenden.

Viele Grüße,
Roland

von Klaus M. (meinzinet)


Lesenswert?

Hallo
ich hab da mal ne Frage bezüglich schreiben auf die SD Karte.
Habe eine 2 GB SD Karte auf welcher ich eine Datei erzeuge und in diese 
Datei Text schreibe.
Das funktioniert auch so, aber der letzte Schreibvorgang auf die Karte 
geht jedoch immer verloren, bzw wird nicht gespeichert.

Mach ich was falsch, oder muss ich abschliessend noch eine Funktion 
aufrufen damit die Daten abgespeichert werden?


Übrigens wer SD Karten Slots mit Auswurfmechanismuss benötigt, kann 
diese gerne von mir zum Versandkostenpreis haben.
Sind SMD Kartenslots von Mainboards voll Funktionstüchtig und mit allem 
Drum und drann.

von Werner B. (werner-b)


Lesenswert?

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

von Klaus M. (meinzinet)


Lesenswert?

Also ich machs eigentlich so wie es Testfile von Roland gestanden hat:


        char* command = buffer;
        strcpy(command, "Test.txt");
        struct fat_dir_entry_struct file_entry;
        int8_t result = fat_create_file(dd, command, &file_entry);
        if (result)
  {
          struct fat_file_struct* fd = open_file_in_dir(fs, dd, 
command);
          if(!fd)
          {
            uart_puts_p(PSTR("error opening "));
            uart_puts(command);
            uart_putc('\n');
            continue;
        }

        char* offset_value = command;
        int32_t offset = strtolong(offset_value);
        if(!fat_seek_file(fd, &offset, FAT_SEEK_SET))
        {
          uart_puts_p(PSTR("error seeking on "));
          uart_puts(command);
          uart_putc('\n');
          fat_close_file(fd);
          continue;
        }
              /* write text to file */

          strcpy(buffer, "Text1\r\n");
          uint8_t data_len=strlen(buffer);
          if(fat_write_file(fd, (uint8_t*) buffer, data_len) != 
data_len)
          {
            uart_puts_p(PSTR("error writing to file\n"));
            break;
          }

          strcpy(buffer, "Text2\r\n");
          data_len=strlen(buffer);
          if(fat_write_file(fd, (uint8_t*) buffer, data_len) != 
data_len)
          {
            uart_puts_p(PSTR("error writing to file\r\n"));
            break;
          }

           strcpy(buffer, "ENDE\r\n");
           data_len=strlen(buffer);
           if(fat_write_file(fd, (uint8_t*) buffer, data_len) != 
data_len)
          {
            uart_puts_p(PSTR("error writing to file\r\n"));
            break;
          }
          fat_close_file(fd);
        }
    fat_close_dir(dd);

        /* close file system */
          fat_close(fs);

        /* close partition */
         partition_close(partition);


Wenn ich dann nachschau in der Datei auf der SD Karte, dann seh ich nur 
die ersten zwei Zeilen stehen:

Text1
Text2


Es fehlt jedoch die dritte Zeile :
also ENDE

Jemand ne Idee was ich da falsch mache?

von Klaus M. (meinzinet)


Lesenswert?

Hallo

Habe einen ATMega 64 mit 16MHz Clock.
Als erstes habe ich bemerkt, dass bei meinem Mega64 Clk/4 mit SPI2x 
nicht funktioniert. (Also halber CLK)
SCK ist mit CLK/4 fast gleich langsam wie CLK/128.
Also hab ich CLK/16 mit SPI2x, also CLK/8 verwendet.


Habe die Funktionen wie schon im vorherigen Post gezeigt aufgerufen.


Habe mal mit einem Oszi versucht zu messen wie lange der schreibvorgang 
dauert.
Also mit CLK/128 dauert das schreiben von etwa 25 Zeichen etwa 250 
Millisekunden.
Mit CLK/8 dauert es immer noch etwa 20-30 Milliskunden.
Die Zeiten variieren komischerweise um 5 ms!

Ich meine, mir kommt es bei einem Datenlogger nicht auf Geschwindigkeit 
an, aber es erhöht den stromverbrauch des Datenloggers, weil die CPU 
weniger lang im Sleep Modus ist.

Kann mir hier jemand sagen, ob die Werte stimmen könnten, oder ob das 
normalerweise viel viel schneller geht.

von Klaus M. (meinzinet)


Lesenswert?

Also nur zur Info:

Sollte jemand mal das selbe Problem mit dem Schreiben von Daten auf die 
Karte haben.
Und der letzte ausgeführte Schreibbefehl wird scheinbar nicht 
ausgeführt, also die Daten sind nicht auf der Karte gespeichert worden, 
dann liegt das am SD_RAW_WRITE_BUFFERING welches im sd_raw_config.h 
einzustellen ist.
Der ist bei aktivierten Schreibsupport automatisch eingeschaltet.

Leider wird geht das schreiben im Mittel dadurch aber auch langsamer von 
statten.

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Klaus,

Wenn bei Dir die letzten Bytes nicht mehr auf die Karte geschrieben 
werden, liegt das daran, dass Du bei eingeschaltetem 
SD_RAW_WRITE_BUFFERING vor dem Abstecken der Karte kein sd_raw_sync() 
aufrufst.

Du solltest, genauso wie am PC auch, die Karte nicht während laufender 
Schreibvorgänge abziehen. Weder werden dabei die Daten korrekt 
gesichert, noch ist danach die Integrität des Dateisystems 
sichergestellt. Sehe also einen Weg vor, die Karte ohne Probleme 
abzustecken, z.B. durch
- eine LED, die anzeigt, ob alle Schreibvorgänge abgeschlossen wurden
- einen Taster, der vor dem Abziehen sd_raw_sync() aufruft.

Bzgl. der Schreibgeschwindigkeit: Öffne und schließe bei den einzelnen 
Schreib-/Lesevorgängen die Datei nicht immer neu. Benutze am Anfang 
einmal fat_open_file(), und vor dem Abstecken der Karte fat_close_file() 
(und sd_raw_sync()), dazwischen nicht mehr.
Bedenke auch, dass das Anhängen an eine Datei sehr aufwändig ist, da 
hier immer auch der Verzeichniseintrag und evtl. die FAT aktualisiert 
werden müssen. Stattdessen solltest Du die Datei zu Beginn auf eine 
bestimmte Größe aufblähen (fat_resize_file()), dann an den Anfang 
springen (fat_seek_file()) und von dort aus schreiben. Bedenke auch, 
dass das Schreiben weniger großer Blöcke schneller ist als das Schreiben 
vieler kleiner Blöcke.

SPI mit halbem MCU-Takt (also CLK/4 mit SPI2x) hilft sehr wohl. Auch 
könntest Du mal andere Karten probieren, insbesondere mit kleiner 
Kapazität. Die verwenden FAT16, was auf dem 8Bit-AVR wesentlich 
effizienter funktioniert, und zusätzlich ist die FAT nicht so groß.

Viele Grüße,
Roland

von Werner B. (werner-b)


Lesenswert?

Hmmm,

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

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Werner,

Der FAT-Treiber weiß gar nichts vom sd-raw-Modul. Er benutzt nur die 
Partitionsfunktionen als nächst tieferen Layer.

Aber Du hast recht, vielleicht sollte man darüber nachdenken, eine 
Funktion zum Synchronisieren der Partition bereitzustellen, die dann vom 
FAT-Treiber an einigen naheliegenden Stellen aufgerufen werden kann.

Gruß,
Roland

von Klaus M. (meinzinet)


Lesenswert?

Hallo Roland

Danke für die Antwort, habe alles mittlerweile gut am laufen.

Etwas ist mir jedoch aufgefallen:


Wenn ich FAT_DATETIME_SUPPORT einschalte, weil ich auch das Datum und 
Uhrzeit der Dateierzeugung haben will, überschreibt mir die Funktion
fat_create_file(dd, log_file_name, &file_entry) irgendwo den RAM 
speicher, so dass eine andere meiner Variablen sich verändert.
Es muss irgendwo im code liegen der bei  FAT_DATETIME_SUPPORT 1 
ausgeführt wird.



mfg klaus

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Klaus!

Das halte ich insgesamt für recht unwahrscheinlich, denn der Code für 
FAT_DATETIME_SUPPORT ist recht trivial. Viel wahrscheinlicher ist, dass 
ein Stack-Overflow auftritt, wodurch Daten auf dem Heap (also globale 
Variablen und mit malloc() allokierter Speicher) überschrieben werden. 
Das kann entweder durch einen Programmierfehler passieren oder schlicht 
weil der Speicher knapp wird.

Wie hast Du denn fat_get_datetime() definiert und implementiert?

Gruß,
Roland

von Klaus M. (meinzinet)


Lesenswert?

Hallo Roland

Ich muss mich bei dir entschuldigen:
Deine Software hatte nur indirekt zu tun mit meinem Problem.

Das Problem war wie du schon richtig vermutet hast der HEAP!

Ich habe einen ATMega32 mit 2k SRAM, und habe nicht gerade sparsam mit 
dem SRAM programmiert, daher waren meine Variablen schon fast am Ende 
des SRAM speichers und der HEAP hatte keinen Platz mehr.

Aber nun läufts. Danke nochmals für den Hinweis.

Und für diejenigen die interessiert wie man am besten feststellen kann 
wo SRAM Variablen liegen (Adresse) und wo der HEAP Anfängt:

Öffnet die MAIN.SYM und sucht dort __bss_end.
Bei mir nun :
008005f5 B battery
00800635 B time_
00800645 B battery_type
00800646 B time_delta_i
0080064a B time2zero
0080064e B __bss_end                <------------

Ab der Adresse beginnt der HEAP.
Von der maximalen SRAM Speicherstelle abwärts liegt der STACK
Wenn sich STACK und HEAP in die Quere kommen hat man ein großes 
Problem!!

Wer das noch genauer lesen will schaut mal hier nach
http://www.nongnu.org/avr-libc/user-manual/malloc.html
oder auch in Deutsch das Tutorial :
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Klaus,

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

Viele Grüße,
Roland

von Torsten S. (tse)


Lesenswert?

Hallo,

Rolands SD-Reader, um wenige Funktionen erweitert, benutze ich nun schon 
eine ganze Weile. 24/7 im Dauereinsatz. Ohne Ausfälle. Der älteste 
Eintrag auf der SD-Karte ist 15.10.2006. Das Teil läuft so gut, das mich 
nicht mehr traue den nochmal anzufassen. ;)

Deswegen habe ich die Hardware neu aufgebaut. Diesmal besser, also mit 
3,3V-Regler, anständigem Levelshifter zur Pegelwandlung und beschalteten 
Pins am Kartenhalter für Karte gesteckt und Schreibschutz aktiviert.

Nur mit letzterem habe ich Probleme, alles andere funktioniert sehr gut 
wie erwartet.

Um genau zu sein ist es die Funtion "sd_raw_locked()" welche bei mir 
genau anders herum funktioniert. Bei meinem Kartenhalter ist es so, das 
der Kontakt geschlossen ist wenn der Schreibschutz-Schieber auf Stellung 
"nicht schreibgeschützt" steht.

Ist es bei Euch genauso?

Vielleicht habe ich ein exotisches Exemplar erwischt welches die 
Kontakte
andersrum schaltet.

Um die Verwirrung perfekt zu machen, habe ich mal in der Funktion

uint8_t sd_raw_write(offset_t offset, const uint8_t* buffer, uintptr_t 
length)

get_pin_locked() durch
sd_raw_locked() ersetzt. Dann geht es ebensowenig.

Bin ratlos.
Torsten

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Torsten,

Toll dass Dein Logger so einwandfrei arbeitet.

Wenn der Schreibschutz bei Dir andersrum funktioniert, dann ist das doch 
auch ok. Bei sd_raw_locked() ist übrigens über die Doku festgelegt, in 
welchen Fällen TRUE bzw. FALSE zurückgegeben wird. get_pin_locked() 
hingegen liefert direkt den Zustand des entsprechenden Bits im 
Portregister.

Bist Du Dir sicher dass der Schreibschutzschalter wirklich "aus" ist, 
wenn der Kartenhalter "ein" meldet? Ich komme da immer mit der 
Markierung auf der Karte selbst durcheinander, die oft nur aus einem 
Pfeil in Form eines Dreiecks besteht. Da frage ich mich dann oft, ist 
der Schreibschutz nun in Richtung des Pfeils aktiv? Oder doch eher am 
dicken Ende? Kannst Du das mit einem PC-Kartenleser nachprüfen?

Im Übrigen hatte ich mit dem Schreibschutzschalter am Sockel meines 
mega-eth auch Probleme, dort funktioniert er gar nicht.

Gruß,
Roland

von Esther L. (lara)


Lesenswert?

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

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

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

von Torsten S. (tse)


Lesenswert?

Ja, ich habe das mehrmals mit dem Kartenleser überprüft.

Der Schieber muß in Richtung Kontakte zeigen, dann ist er nicht 
schreibgeschützt.

Nach flüchtigem Betrachten von Esther Ls. Quelltext sieht es scheinbar 
so aus das der Kontakt dort genauso schaltet.

Torsten

von Birger Z. (nohelp)


Lesenswert?

Hab mich nun auch mit der SD-Karte beschäftigt und den Code von R.R. 
ausprobiert - bisher leider ohne Erfolg. Was bedeutet "opening partition 
failed", das bei mir erscheint, sobald ich eine Karte einstecke?

Die Schaltkontakte meines Kartensockels schalten beide gegen Masse, als 
Widerstände hab ich 3K und 1,5K verwendet und die Spannungsversorgung 
erfolgt über zwei Dioden mit 'nem 100nF Kondensator und 100K gegen 
Masse. Als Prozessor verwende ich einen ATmega128 mit 14,7456 MHz.

von Roland R. (roland) Benutzerseite


Lesenswert?

Anscheinend kann zwar die Karte angesteuert, das Dateisystem aber nicht 
geöffnet werden. Hast Du mal einen Schaltplan von Deinem Aufbau? Wie 
machst Du das Level-Shifting? Welche Karte benutzt Du? Wie wurde sie 
formatiert?

Gruß,
Roland

von Klaus M. (meinzinet)


Lesenswert?

Also ich löse das Problem mit Leveln auch mit Widerständen.
Man sollte hier aber unbedingt mit dem Oszi die Kurvenverläufe der 
Leitungen an der SD Karte anschauen.
Es sollte ein schöner Rechteck sein. Da durch die Widerstände eine RC 
Glid entsteht, wird auch das Lade und entladeverhalten eines 
Kondonsators sichtbar.

Ich habe bei meinem Aufbau die Erfahrung gemacht hier den Takt lieber 
etwas langsamer zu machen.
Bei mir lief das eine zeit lang sehr gut, aber aus unersichtlichen 
Gründen war ab einer gewissen Dauer kein Schreiben auf die Karte 
möglich.
Als ich den Takt auf die nächst mögliche Stufe verkleinert hatte, lief 
alles einwandfrei, auch auf längere Dauer gesehen.

von Birger Z. (nohelp)


Lesenswert?

Bin jetzt doch noch einen Schritt weiter gekommen.
Nach Durchstöbern der ganzen Config-Files habe ich
1
#define FAT_FAT32_SUPPORT SD_RAW_SDHC
in
1
#define FAT_FAT32_SUPPORT 1
geändert. Damit konnte ich dann zwei meiner SD-Karten ansteuern, meine 
16MB MMC Karte wollte jedoch immer noch nicht. Außerdem machte eine der 
beiden SD-Karten Ärger beim Anzeigen des Inhaltsverzeichnisses. Hier 
geriet die Software in eine Endlosausgabe, da half nur Reset. Hab die 
Karte dann unter Windows neu formatiert und es ging dann auch mit 
dieser. Woran es lag, kann ich nicht sagen. Vielleicht zu lange 
Dateinamen.

Was mir noch so auffiel, cat gibt am Ende meist ein paar Bytes zuviel 
aus.

von Roland R. (roland) Benutzerseite


Lesenswert?

Ja, Unterstützung für Karten >= 4GB ist standardmäßig deaktiviert. Dafür 
einfach SD_RAW_SDHC in sd_raw_config.h auf 1 setzen, die Änderung an 
FAT_FAT32_SUPPORT ist dann nicht nötig.

Die 16MB-Karte ist vermutlich mit FAT12 formatiert, wofür meine Software 
keine Unterstützung bietet.

Die Implementierung von "cat" ist simpel gehalten, es werden pro Zeile 
immer acht Bytes ausgegeben, egal ob die Dateilänge durch acht teilbar 
ist oder nicht. Die zu viel ausgegebenen Bytes stammen dann von der 
Zeile drüber.

Gruß,
Roland

von No Name (Gast)


Lesenswert?

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

von meini (Gast)


Lesenswert?

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

von Gerd (Gast)


Lesenswert?

Ich habe heute fünf Karten getestet mit der Version 20081121. Das 
Ergebnis:
Hama 256MB (manuf. 0x04):
Wird sofort erkannt. Die Befehle müssen öfters wiederholt werden, damit 
die Karte arbeitet.
Kingston 256MB:
Wird sofort erkannt, arbeitet ohne erkennbare Probleme
Delkin eFilm 64MB:
Wird fast immer sofort erkannt. Wenn sie erkannt wird, läuft sie 
einwandfrei.

Kingston 1GB:
Wird nicht erkannt
Canon 32MB:
Wird nicht erkannt

SDHC-Erkennung ist ein. Controller ist der Atmega644P.

Gruß Gerd

von meini (Gast)


Lesenswert?

Also meine Kingston 1GB Karte, erst vor wenigen wochen gekauft, lief 
sofort.

Du verwendest doch Widerstandsteiler, oder?
Könnte es demnach nicht dem von mir bereits erwähnten Problemen mit zu 
hohen Clock zusammenhängen? (Machs einfach mal langsamer)

von Birger Z. (nohelp)


Lesenswert?

Hab mir mittlerweile statt der Widerstandsteiler 'nen 74LVX244 
eingebaut, seitdem gehen alle meine Karten auch bei 16MHz Quarztakt, was 
vorher nicht der Fall war. Nach weiterem Ausprobieren sehe ich, dass das 
Programm hängt, wenn ich eine Datei mit dem "cat" Befehl ausgebe und 
anschließend eine neue Karte einstecke. Diese wird mit dem init-Befehl 
nicht mehr richtig angemeldet, weshalb dann nur Reset hilft. Da fehlt 
also noch irgendwas im Quellcode. Leider bin ich in der Materie nicht 
soweit drin um sagen zu können, was da genau schief geht.

von meini (Gast)


Angehängte Dateien:

Lesenswert?

Also ich hab die SD_RAW.C Datei etwas verändert.

Diese Änderung bewirkt eine art Timeout, welche das Aufhängen der 
Software verhindert.

Die Stellen im Code sind mit JKLM gekennzeichet.
Zustande kommt das Aufhängen, wenn die Karte keine oder falsche 
Rückgabewerte liefert. Sollte wenn alles funktioniert ja nie auftreten, 
aber was funkt schon immer.

Ich hoffe das hilft.

gruß meini

von Gerd (Gast)


Lesenswert?

Hallo meini,

>Du verwendest doch Widerstandsteiler, oder?
Richtig!
Ich bin gerade verschieden Sachen am Durchprobieren und mir fällt auf, 
das Ulrich Radig in seiner SW auch mit niedrigsten SPI-Takt 
initialisiert und dann auf maximalen SPI-Takt hochschaltet. Mit dieser 
SW laufen alle Karten die ich habe. Zur Zeit versuche ich mit 
Debugausgaben herauszufinden, was schief läuft.

Atmega644p
14,7456MHz
Widerstandsteiler nach Radig.

Gruß Gerd

von meini (Gast)


Lesenswert?

Hallo Gerd

Also das Initialisieren mit niedrigstem Takt macht auch Rolands 
software.
Anschließend wird dann auf den Arbeitstakt hochgeschaltet.

Ja ich arbeite mit widerstandsteilern. Bis auf die genannten Probleme 
funktioniert es immer auf anhieb.

Das Aufhängen kommt meist daher, dass die software auf ein Rückgabebyte 
wartet. Kommt es nicht, oder kommt ein falsches Byte zurück bleibt die 
Software dort in der schleife stecken.
Es wrid zuerst ein Kommandobyte an die Karte geschrieben, und danach auf 
die Rückmeldung gewaretet.

Bei mir ist es meist schiefgelaufen, wenn ich die Karte aus dem Slot 
genommen habe.

glus klaus

von Torsten S. (tse)


Lesenswert?

Hallo Gerd,

Auch die 3,3V Versorgung der Karte könnte die Ursache für so ein 
Verhalten sein. Wenn noch nicht geschehen, dann unbedingt die Dioden 
gegen einen geeigneten Festspannungsregler tauschen.

Torsten

von Gerd (Gast)


Lesenswert?

Die 3,3V Spannungsversorgung ist durch einen LM317 gegeben. Wie gesagt, 
kriege ich nicht alle SD-Karten mit Rolands Programm initialisiert. Da 
ich gerade noch ein anderes Problem lösen muss, das damit nichts zu tun 
hat, wird meine Rückmeldung zu diesem Thema erst in den nächsten Tagen 
kommen.
Wenn ich Ulrichs Programm verwende, werden alle Karten erkannt. Da sieht 
die Init so aus:
1
//############################################################################
2
//Routine zur Initialisierung der MMC/SD-Karte (SPI-MODE)
3
unsigned char mmc_init ()
4
//############################################################################
5
{
6
  unsigned int Timeout = 0;
7
  
8
  //Konfiguration des Ports an der die MMC/SD-Karte angeschlossen wurde
9
  MMC_Direction_REG &=~(1<<SPI_DI);      //Setzen von Pin MMC_DI auf Input
10
  MMC_Direction_REG |= (1<<SPI_Clock);    //Setzen von Pin MMC_Clock auf Output
11
  MMC_Direction_REG |= (1<<SPI_DO);      //Setzen von Pin MMC_DO auf Output
12
  MMC_Direction_REG |= (1<<MMC_Chip_Select);  //Setzen von Pin MMC_Chip_Select auf Output
13
  MMC_Direction_REG |= (1<<SPI_SS);  
14
  MMC_Write |= (1<<MMC_Chip_Select);      //Setzt den Pin MMC_Chip_Select auf High Pegel
15
16
  for(unsigned char a=0;a<200;a++){
17
  nop();
18
  };    //Wartet eine kurze Zeit
19
20
  #if SPI_Mode
21
    //Aktiviren des SPI - Bus, Clock = Idel LOW
22
    //SPI Clock teilen durch 128
23
    SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1); //Enable SPI, SPI in Master Mode  
24
    SPSR = (0<<SPI2X);
25
  #endif
26
  
27
  //Initialisiere MMC/SD-Karte in den SPI-Mode
28
  for (unsigned char b = 0;b<0x0f;b++) //Sendet min 74+ Clocks an die MMC/SD-Karte
29
    {
30
    mmc_write_byte(0xff);
31
    }
32
  
33
  //Sendet Commando CMD0 an MMC/SD-Karte
34
  unsigned char CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95};
35
  while(mmc_write_command (CMD) !=1)
36
  {
37
    if (Timeout++ > 200)
38
      {
39
      MMC_Disable();
40
      return(1); //Abbruch bei Commando1 (Return Code1)
41
      }
42
  }
43
  //Sendet Commando CMD1 an MMC/SD-Karte
44
  Timeout = 0;
45
  CMD[0] = 0x41;//Commando 1
46
  CMD[5] = 0xFF;
47
  while( mmc_write_command (CMD) !=0)
48
  {
49
    if (Timeout++ > 400)
50
      {
51
      MMC_Disable();
52
      return(2); //Abbruch bei Commando2 (Return Code2)
53
      }
54
  }
55
  #if SPI_Mode
56
    //SPI Bus auf max Geschwindigkeit
57
    SPCR &= ~((1<<SPR0) | (1<<SPR1));
58
    SPSR = SPSR|(1<<SPI2X);
59
  #endif
60
  
61
  //set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
62
  MMC_Disable();
63
  return(0);
64
}
Ich melde mich wieder, wenn ich das andere Problem gelöst habe.

Gruß Gerd

von Toblachs (Gast)


Lesenswert?

Hey,

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

von Birger Z. (nohelp)


Lesenswert?

Warum sollten wir diesen Thread in Assembler umschreiben? Such mal im 
Forum danach. Da hab ich sowas schon gesehen. So eine komplexe Aufgabe 
wie die SD-Karte ist doch keine geeignete Aufgabe für Assembler-only. Du 
kannst dir natürlich das compilierte Listing File anschauen und daraus 
deinen Code stricken.

Hallo meini,
es ist mit deinem Time-Out-Schleifen zwar etwas besser geworden (besten 
Dank dafür) aber noch nicht beseitigt. Spiel ich etwas rum, schaffe ich 
es weiterhin, die Software schnell zu verwirren.

Da werd ich mir die U.R. SW auch noch mal ansehen. Letztlich such ich 
eine Software, die dauerhaft ohne manuellen Eingriff funktioniert.

von Daniel B. (dbuergin)


Lesenswert?

Hallo

Habe mir einen Temperatur Logger auf Basis eines ATmega128 Boards und 
einem SD-Kartenleser gebaut. Funktioniert soweit wunderbar.
Danke an alle Beteiligten und vorallem an Roland Riegel für seine 
Software.

Zwei Sachen sind mir aber noch nicht ganz klar:

1. Wie hänge ich Daten an ein bestehendes File an.
   Stimmt das folgendes Vorgehen:
   - sd_raw_init()
   - partition_open()
   - fat_open()
   - fat_get_dir_entry_of_path()
   - fat_open_dir()

   - open_file_in_dir(fs, dd, "mmc.txt");
   - fat_seek_file(fd, &write_offset, FAT_SEEK_END)) // write_offset = 0
   - fat_write_file(fd, (uint8_t*) "Zeile2\n", 7)
   - sd_raw_sync();
   - fat_close_file(fd);

   - fat_close(fs);
   - partition_close(partition);

Ganz falsch kann es nicht sein, mein File hat die Zeile drin und ist auf 
Windows und Linux noch lesbar ;-)
Oder anders gefragt, ist mir nicht klar, ob ich nun das File zuerst mit 
resize vergrössern muss oder direkt reinschreiben kann ?

2. Sicheres Vorgehen gegen Datenverlust

Da mein Logger alle 60s einen Datensatz von ca. 25 Bytes in das File 
schreiben wird, kann ich doch jedesmal das File öffnen, die Daten 
reinschreiben und alles wieder schliessen, so dass das Filesystem ok 
ist. Oder spricht etwas dagegen ?
Ich weiss, ich könnte das File am Anfang öffnen, im Minutentakt 
reinschreiben und am Schluss, z.B. nach einem Button-klick, schliessen 
und gut. Aber was passiert dazwischen, wenn der Strom ausfällt oder so ? 
Daten wohl weg, und Filesystem korrupt.

Besten Dank und Gruss

Daniel

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Daniel,

1. Das stimmt so. fat_resize_file() bietet sich bei vielen oder großen 
Anhängeoperationen an, um die Datei im Vorhinein zu vergrößern, so dass 
der Verzeichniseintrag (der die Größe enthält) nicht bei jedem 
fat_write_file() geschrieben werden muss.

2. Wie Du es machst ist egal. Wichtig ist nur der Aufruf von 
sd_raw_sync(). Das ganze Drumherum der Handles ändert nichts an der 
Konsistenz des Dateisystems, sondern puffert nur einige wichtige 
Informationen über die Partition, das Dateisystem, die Datei usw.. Wenn 
Du nach fat_write_file() sd_raw_sync() aufrufst, ist alles in einem 
konsistenten Zustand. Wenn Du den Kartentausch nur in ausgeschaltetem 
Zustand vorsiehst, brauchst Du nie fat_close_file(), fat_close() etc. 
aufrufen.

Viele Grüße,
Roland

von Daniel B. (dbuergin)


Lesenswert?

Super, besten Dank

Daniel

von Alexander H. (sonium)


Lesenswert?

Hi, ich habe anscheinend Probleme beim Aufbau der Schaltung, und weiß 
langsam nichtmehr wo der Fehler noch sein könnte. Sobald ich 
get_pin_available() und get_pin_locked() auf null setze produziert 
avrdude nach dem flashen beim fuse-check nen Fehler, aber ist ja 
irgendwie auch logisch und dürfte denk ich nicht viel machen. Allerdings 
herrscht auf dem UART dann auch absolute Stille. Beim Spannungsteiler 
hab ich 2k2 und 4k7 Ohm, aber Hauptsache das Verhältniss ist ungefähr 
das gleiche, oder? Die Versorungsspannung lege ich zwischen GND und der 
Karte mit einem Netzteil an, der AVR wird über den USB ISP versorgt, der 
ja Erdfrei sein müsste. Die Karte funktioniert am PC und der mC ist ein 
ATmega32. So, mehr fällt mir eigentlich nichtmehr ein.

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Alexander,

> Sobald ich
> get_pin_available() und get_pin_locked() auf null setze produziert
> avrdude nach dem flashen beim fuse-check nen Fehler, aber ist ja
> irgendwie auch logisch und dürfte denk ich nicht viel machen.

Was ist daran logisch?? Was hat ein Ändern von Konstanten im Programm 
mit den Fuses und dem Verhalten von avrdude zu tun?

Setze
  #define configure_pin_available() /* empty */
  #define configure_pin_locked() /* empty */
  #define get_pin_available() 0
  #define get_pin_locked 1

> Beim Spannungsteiler
> hab ich 2k2 und 4k7 Ohm, aber Hauptsache das Verhältniss ist ungefähr
> das gleiche, oder?

Im Prinzip schon. Denk aber bitte dran dass je größer die 
Widerstandswerte sind desto flacher werden die Signalflanken.

> Die Versorungsspannung lege ich zwischen GND und der
> Karte mit einem Netzteil an, der AVR wird über den USB ISP versorgt, der
> ja Erdfrei sein müsste. Die Karte funktioniert am PC und der mC ist ein
> ATmega32. So, mehr fällt mir eigentlich nichtmehr ein.

Kannst Du mal nen Schaltplan skizzieren? Das mit der Erde ist mir nicht 
ganz klar. Versorge mal alles aus einer einzigen Spannungsquelle und 
spendier der Karte einen richtigen Regler.

Gruß,
Roland

von Alexander H. (sonium)


Lesenswert?

danke für die schnelle Antwort. Ich hab das ganze jetzt auf 3.3V laufen, 
da der Atmega32 damit auch noch läuft. Jetzt kommt er immerhin zu dem 
Schluss dass "MMC/SD initialization failed". Ich hab herausgefunden, 
dass

response = sd_raw_send_command(CMD_GO_IDLE_STATE, 0);

nicht die erwartete Antwort sondern 0xff liefert.

von Roland R. (roland) Benutzerseite


Lesenswert?

Alles auf 3,3V laufen zu lassen ist natürlich auch ok.

Ein paar Ideen:
- Blockkondensatoren (50uF und 100nF) direkt an der Karte
- möglichst kurze SPI-Leitungen
- ISP-Programmer vor uC-Start abziehen (zu lange Leitungen)
- Pinbelegung an der Karte überprüfen
- MISO (also DO der Karte) mit Pullup ca. 50k auf 3,3V
- Signale und Vcc mit Oszilloskop anschauen

Die Karte kann beim Initialisieren und v.a. auch bei Zugriffen recht 
viel Strom ziehen, dass sollte die Spannungsquelle liefern können. Was 
hast Du sonst an der Schaltung hängen? Hast Du einen festen Aufbau auf 
Platine oder eine Freiluftverdrahtung? Welche Änderungen hast Du an der 
Software im Vergleich zum Original vorgenommen?

Viele Grüße,
Roland

von Gast (Gast)


Lesenswert?

Hi.

Ich habe ein Problem mit dem Debuggen, wenn ich die SD-Bibliothek 
eingebunden habe. Solange ich nur die Karte initialisiere ist alles 
I.O.. Sobald ich das öffenen der Partition mit in meinen Code aufnehme, 
bekomme ich Abstürze von AVR-Studio.

Ich arbeite mit
- Rolands Bibliothek Version 2008-11-21
- AVR-Studio 4.15.623
- WINAVR 20081205
- JTAGICEmkII (Firmware-Update von AVR-Studio 4.15.623)
- ATmega2560 oder ATmega644

Sobald ich diesen Codeabschnitt mit reinehme, stürzt AVR-Studio mit 
einem MFC-Fehler ab sobald ich irgendwo in partition_open() einen 
Breakpoint setze:
1
if(!partition)
2
{
3
    /* If the partition did not open, assume the storage device
4
     * is a "superfloppy", i.e. has no MBR.
5
     */
6
     partition = partition_open(sd_raw_read,
7
                               sd_raw_read_interval,
8
                               sd_raw_write,
9
                               sd_raw_write_interval,
10
                               -1
11
                              );
12
    if(!partition)
13
    {
14
#if DEBUG
15
        uart_puts_p(PSTR("opening partition failed\n"));
16
#endif
17
        continue;
18
    }
19
}

Hat irgendjemand etwas ähnliches beobachtet und kann mir vieleicht einen 
Tip geben? Ich kann es mir nicht erklären, was da genau passiert.

von Roland R. (roland) Benutzerseite


Lesenswert?

Hm, da habe ich keine Ahnung, ich arbeite nicht mit dem AVR-Studio. 
Vielleicht kommt es mit den Funktionspointern und den zugehörigen 
typedefs durcheinander? Schon mal eine andere Studio-Version 
ausprobiert?

Gruß,
Roland

von Gast (Gast)


Lesenswert?

Ich habe schon die neue 4.16-beta ausprobiert, aber da ist es das 
gleiche. Ältere Versionen muß ich nochmal raussuchen.

Ich schau mir mal die Funktionspointer an.

Danke

von Gast (Gast)


Lesenswert?

Hi,

wollte nochmal Feedback geben, dass die unerklärlichen Abstürze mit

- AVR-Studio 4.14.589

nicht auftreten. Dafür ist das Debuggen nicht so komfortabel, weil 
AVR-Studio nicht automatisch die Breakpoints anspringt. Naja, irgendwas 
ist ja immer.

von Marcel (Gast)


Lesenswert?

Abend,

ich habe Probleme beim öffnen/finden einer Datei. Controller ist ein 
ATmega32. Kann mir mal bitte jemand auf die Sprünge helfen, was ich 
falsch mache bzw. was ich vergessen habe?
Hier steigt mein Programm aus:
if(!fd)
{
   vLCD_Control(ZEILE_2, "error opening ");
}

Und hier der ganze Code:

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

von Torsten S. (tse)


Lesenswert?

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

Torsten

von Marcel (Gast)


Lesenswert?

Die Datei wurde unter Windows erstellt, test.TXT hatte aber auch nichts 
gebracht. Ist denn die Art und Weise, wie ich das FAT16 System 
initialisiere und die Datei suche/öffne so richtig?

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Marcel,

Ich finde Deinen Code mit den ganzen verschachtelten ifs etwas 
unübersichtlich. Mach es lieber so:
1
  if(!partition)
2
  {
3
    /* lcd error message */
4
    return;
5
  }
6
7
  /* ... */
8
9
  if(!fs)
10
  {
11
    /* output lcd error message */
12
    return;
13
  }
14
15
  /* etc. */

Und vergleiche die zurückgegebenen Handles bitte nicht mit FALSE, das 
sieht so aus als würde die Funktion einen Wahrheitswert zurückgeben, was 
sie aber nicht tut. Entweder "== 0" bzw. "!= 0" oder den Handle direkt 
als Wahrheitswert verwenden (wie im Ausschnitt oben).

Wenn ich mich durch die missglückte Formatierung des Codeausschnitts 
nicht in die Irre habe führen lassen, versuchst Du, das Dateisystem auch 
dann zu öffnen, wenn die Partition gar nicht geöffnet werden konnte.

Ansonsten hat Torsten Recht, die aktuelle sdreader-Version behandelt die 
Groß-/Kleinschreibung von Dateien nicht immer korrekt, die unter Windows 
NT/2000/XP/Vista angelegt wurden. Vielleicht also statt dem Öffnen der 
Datei erst mal versuchen, alle Dateien auf der Karte aufzulisten.

Wenn die Groß-/Kleinschreibung für Dich ein Problem sein sollte, findest 
Du in dem folgenden Beitrag den Patch, der das Problem behebt:
  Beitrag "Re: MMC/SD-Karte mit FAT16 an AVR"

Gruß,
Roland

von Stefan (Gast)


Lesenswert?

Hallo Roland,

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

Ich bekomme bei der ersten if-Abfrage stetig eine response von 255, d.h. 
die for-schleife wird nie verlassen, da die vorletzte if-Abfrage nie 
wahr wird. Kann die Erklärung dafür sein, das meine 16MB Panasonic Karte 
nicht richtig funktioniert? In Windos kann ich sie ganz normal lesen und 
beschreiben.
Habe einen ATMega168 mit deiner exakten Verschaltung. Hoffe, du hast 
einen Tip für mich.

Gruß Stefan

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Stefan,

Hättest Du für den Anfang nicht vielleicht noch eine etwas größere (d.h. 
neuere) SD-Karte zum Testen? Ich weiß nicht, wie genau sich diese alten 
MMC-Karten an die Spezifikation halten. Auch habe ich keine hier, mit 
der ich selbst testen könnte.

Zudem wirst Du Probleme mit dem Zugriff auf die Dateien bekommen, denn 
die 16MB werden normalerweise noch mit FAT12 verwaltet, wofür der 
sd-reader keine Unterstützung bietet.

Gruß,
Roland

von Marcel (Gast)


Lesenswert?

Abend,

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

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

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

SChönes Wochenende

von Michael W. (das-micha)


Lesenswert?

Hallo,

kann mir einer die Eagle-Datei (Schaltplan) in eine PDF/Bild umwandeln? 
Ich überlege im moment gerade ein kleines Sprachausgabe-Modul zu 
basteln, als externen, leicht verwaltbaren Speicher würde sich eine 
SD-Karte da ja anbieten, einfach neue "WAV's" aufspielen und schon 
klappt es mit der ausgabe ;-)

von Gast (Gast)


Lesenswert?

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

Ansonsten ausdrucken und z.B. freepdfxp benutzen.

von Stefan (Gast)


Lesenswert?

Hallo Roland,

Du hattest wie immer den richtigen Riecher bzgl. meiner Speicherkarte, 
die nur 16MB groß ist. Habe mir eine 2GB Karte gekauft, jetzt scheint es 
zu funktionieren!! Meine 16MB Karte ist übrigens keine MMC, sondern auch 
eine SD, aber egal...
Vielen Dank nochmal für die Mühe.

Stefan

von Michael W. (das-micha)


Lesenswert?

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

von Gast (Gast)


Lesenswert?

Dann lade Dir sie Dir doch bei Cadsoft runter. Nach der Installation als 
freeware lizensieren. Damit kann man zwar nur Platinen mit einem 
Schaltplanblatt und nur 100x80mm zaubern, aber öffnen kann man auch 
größere Projekte.

von Roland R. (roland) Benutzerseite


Lesenswert?

Michael W. wrote:
> kann mir einer die Eagle-Datei (Schaltplan) in eine PDF/Bild umwandeln?

Wenn Du den Thread mal nach "pdf" oder "png" durchsucht hättest, wärst 
Du auf diesen Beitrag gestoßen:
  Beitrag "Re: MMC/SD-Karte mit FAT16 an AVR"

Gruß,
Roland

von Alex (Gast)


Lesenswert?

Hallo,

ich wollte diese Schaltung nachbauen, aber habe noch 2 Fragen:

Sehe ich das richtig, dass J1 der Slot für die SD/MMC Karte ist?
Worum handelt es sich bei JP3 und JP4?

Danke
Alex

von Alex (Gast)


Lesenswert?

Noch etwas vergessen:

Also J1 muss ja der SD Slot sein, was bedeuten Pins 10-12? Eine SD Karte 
hat doch nur 9 Pins?

Welchen Wert sollte man für C5 nehmen?

Hätte jemand die genaue Bezeichnung von Q1 für mich?

Vielen Dank!

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Alex,

> Sehe ich das richtig, dass J1 der Slot für die SD/MMC Karte ist?

Ja klar.

> Worum handelt es sich bei JP3 und JP4?

Das ist die UART.

> Also J1 muss ja der SD Slot sein, was bedeuten Pins 10-12?

Anschlüsse für Card-Detect- bzw. Write-Lock-Schalter. Nicht zwingend 
notwendig.

> Welchen Wert sollte man für C5 nehmen?

Je nach Netzteil, 50µF bis 200µF sind allemal ok.

> Hätte jemand die genaue Bezeichnung von Q1 für mich?

Jeder x-beliebige 16MHz-Grundton-Quarz. Kannst auch ne andere Frequenz 
nehmen, musst dann aber die Software anpassen.
Reichelt: http://www.reichelt.de/?ARTICLE=32852

Gruß,
Roland

von Alex (Gast)


Lesenswert?

Roland,

vielen dank!

Grüße
Alex

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

Hallo zusammen!

Ein neues sd-reader-Release ist fertig (siehe Anhang). Hauptsächlich 
enthält es Bugfixes und einige Schönheitskorrekturen.

Im einzelnen:
- Benutze Info über Groß-/Kleinschreibung für Dateinamen und
  -erweiterungen, wie sie von Windows NT und später geschrieben werden.
- Standard-Pinkonfiguration für den ATmega328.
- MMC/SD/SDHC-Unterscheidung korrigiert.
- Blockpufferung korrigiert.
- Größenberechnung für FAT16 bei Verwendung einer FAT32-Konfiguration
  korrigiert.
- Kompilierungsfehler bei Nur-Lese-Konfiguration beseitigt.
- Korrekte Logik für den Schreibschutz.
- Vereinfachte Einbindung in C++-Anwendungen.

Neu auf der Projekt-Homepage gibt es auch einen neuen, verbesserten 
Schaltplan sowie eine FAQ-Seite
  http://www.roland-riegel.de/sd-reader/faq/
und eine Benchmark-Seite
  http://www.roland-riegel.de/sd-reader/benchmarks/

Viel Spaß damit,
Roland

von Jan (Gast)


Lesenswert?

Ich habe ein kleines Problem, ich hab ein Board mit einem Atmega32, die 
SD-Karte wird erkannt und ich kann Daten aus einem File lesen. Schreiben 
hat auch funktioniert, ich habe aber etwas am Code rumgebastelt und 
jetzt funktioniert es nicht mehr. Es kommt jedoch keine Fehlermeldung. 
Hier mal ein Teil des Codes, der obere Teil, der fehlt, ist identisch 
mit dem original Code. Vieleicht sieht ja jemand mein Fehler, ich bin 
schon am verzweifeln.
1
  while(fat_read_dir(dd, &directory))
2
      {
3
          if(strcmp(directory.long_name, "test.txt") == 0)
4
          {
5
            
6
           strcpy(test,directory.long_name);
7
    
8
           uart_puts(test); 
9
           break;   
10
          }
11
12
      }
13
14
    struct fat_file_struct * file = fat_open_file(fs,&directory);
15
    if(!file)
16
    {
17
      uart_puts_p(PSTR("file error\n"));
18
    }
19
    else
20
    {
21
      uart_puts_p(PSTR("file ok\n"));
22
    }
23
24
    
25
    char write[] = "test";
26
    
27
    int data_len = 1+strlen(write);
28
    
29
    if(fat_write_file(file, (uint8_t*) write, data_len) != data_len)
30
    {
31
      uart_puts_p(PSTR("error writing to file\n"));
32
      break;
33
    }
34
    else
35
    {
36
      uart_puts("file beschrieben \n");
37
    }
38
39
    
40
    fat_close_file (file);
41
42
    return 0;

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Jan,

Jan wrote:
> Ich habe ein kleines Problem, ich hab ein Board mit einem Atmega32, die
> SD-Karte wird erkannt und ich kann Daten aus einem File lesen.

Ok.

> Schreiben
> hat auch funktioniert, ich habe aber etwas am Code rumgebastelt und
> jetzt funktioniert es nicht mehr. Es kommt jedoch keine Fehlermeldung.

Was genau hast Du wo herumgebastelt? Was funktioniert nicht mehr? Was 
soll funktionieren? Was passiert stattdessen (oder eben nicht)?
1
>   while(fat_read_dir(dd, &directory))
2
>       {
3
>           if(strcmp(directory.long_name, "test.txt") == 0)
4
>           {
5
> 
6
>            strcpy(test,directory.long_name);
7
> 
8
>            uart_puts(test);
9
>            break;
10
>           }
11
> 
12
>       }

Was passiert (oder soll passieren), wenn die Datei nicht gefunden wird? 
In Deinem Code wird einfach weitergemacht, was dann natürlich 
schiefgeht. (Noch ein hypothetischer Fall: Wass passiert, wenn 
"test.txt" ein Ordner ist?)

Und: Warum kopierst Du den Dateinamen in einen mysteriösen Puffer 
(dessen Größe hoffentlich ausreichend ist), wenn Du directory.long_name 
auch direkt ausgeben kannst?
1
>     struct fat_file_struct * file = fat_open_file(fs,&directory);
2
>     if(!file)
3
>     {
4
>       uart_puts_p(PSTR("file error\n"));
5
>     }
6
>     else
7
>     {
8
>       uart_puts_p(PSTR("file ok\n"));
9
>     }

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

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

Warum "break"? Auf welche Schleife bezieht sich das?

Also, knapp gesagt: Rechne immer mit Fehlern und reagiere darauf, und 
zwar nicht nur mit einer Fehlermeldung über UART!

Gruß,
Roland

von Thorsten S. (Gast)


Lesenswert?

Hallo Roland,

ich habe Deine Lib mit verschiedenen Karten ausprobiert, allerdings 
bleibe ich immer beim Öffnen des Filesystems hängen.

Windows erkennt die Karten (16MB, 32MB,64MB,2GB) ganz normal.

Habe einige Karten in einer Digitalkamera neu formatiert.

Ich verwende die ersten Teile aus Deiner main.c, daher sollte es 
eigentlich funktionieren (?).

Das Init klappt auch soweit, da bekomme ich keinen Fehler. Partition 
scheint auch ok zu sein.

Hardwareaufbau ist ein AtMega644 16Mhz, SD-Karte mit 3,3V Regler und 
Widerständen und Abblockkondensatoren.

Viele Grüße,
Thorsten

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Thorsten,

Mit welchen Dateisystemen sind die Karten formatiert? Zumindest die 
16MB-Karte müsste mit FAT12 formatiert sein, welches von meinem Code 
nicht unterstützt wird. Benutze zur Formatierung bitte Windows oder noch 
besser unter Linux mkdosfs.

Wo genau scheitert fat_open()/fat_read_header()? Füge bitte Haltepunkte 
oder UART-Ausgaben an mehreren Stellen ein und verfolge nach, wo der 
Code aussteigt. Vielleicht magst Du mir per Mail auch mal Deinen Code 
schicken.

Gruß,
Roland

von Thorsten S. (Gast)


Lesenswert?

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

von Thorsten S. (Gast)


Lesenswert?

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

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

von Simon K. (simon) Benutzerseite


Lesenswert?

Hallo,

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

Die Zeile SPSR &= ~(1<<SPIF); ist imho a) Quatsch und b) unnötig. a) 
Löscht man ein Interrupt Flag durch Schreiben einer 1 an der Stelle und 
b) SPIF wird automatisch gelöscht, wenn SPSR mit gesetztem SPIF gelesen 
wurde.

Ich habe aber Probleme die ganze Library in ein Projekt einzubinden, wo 
an der SPI Schnittstelle auch noch ein ENC28J60 hängt. Nach dem 
sd_raw_init funktioniert erst mal nichts mehr.
Überprüft habe ich:
-CPOL und CPHA haben schon mal die gleichen Einstellung bei SD Karte und 
ENC28J60 (beides MODE 0).
-Den SS Pin für die Karte habe ich in den Definitionen umgelegt auf 
einen anderen Port.

Eventuell hast du noch eine Idee welche Aktionen aus deiner Library mit 
einer anderen SPI Library kollidieren könnten.

Danke schon mal!

von Thorsten S. (Gast)


Lesenswert?

So, hier der Code. Die Partition Routine gibt keinen Fehler zurück, der 
Code bleibt in der ersten Anweisung in fat_open hängen, da partition auf 
einmal null zu sein scheint.
1
 /* setup sd card slot */
2
 if(!sd_raw_init())
3
 {
4
    uart_puts_p(PSTR("MMC/SD initialization failed\n"));
5
    _delay_ms(20);
6
    return 0;
7
 }
8
9
 /* open first partition */
10
 struct partition_struct* partition = partition_open(sd_raw_read,
11
                                                            sd_raw_read_interval,
12
                            #if SD_RAW_WRITE_SUPPORT
13
                                                            sd_raw_write,
14
                                                            sd_raw_write_interval,
15
                            #else
16
                                                            0,
17
                                                            0,
18
                            #endif
19
                                                            0
20
                                                           );
21
22
        if(!partition)
23
        {
24
            /* If the partition did not open, assume the storage device
25
             * is a "superfloppy", i.e. has no MBR.
26
             */
27
            partition = partition_open(sd_raw_read,
28
                                       sd_raw_read_interval,
29
                  #if SD_RAW_WRITE_SUPPORT
30
                                       sd_raw_write,
31
                                       sd_raw_write_interval,
32
                  #else
33
                                       0,
34
                                       0,
35
                  #endif
36
                                       -1
37
                                      );
38
            if(!partition)
39
            {
40
                uart_puts("opening partition failed\n");          
41
            }
42
        }
43
44
45
        /* open file system */
46
        struct fat_fs_struct* fs = fat_open(partition);
47
        if(!fs)
48
        {
49
            uart_puts("opening filesystem failed\n");
50
            
51
        }

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

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

von Thorsten S. (Gast)


Lesenswert?

Karten sind jetzt auch Fat16 formatiert.

von Simon K. (simon) Benutzerseite


Lesenswert?

Simon K. wrote:
> Ich habe aber Probleme die ganze Library in ein Projekt einzubinden, wo
> an der SPI Schnittstelle auch noch ein ENC28J60 hängt. Nach dem
> sd_raw_init funktioniert erst mal nichts mehr.

Also:

sd_raw_init() läuft bis zu dieser Stelle:
1
#if !SD_RAW_SAVE_RAM
2
    /* the first block is likely to be accessed first, so precache it here */
3
    raw_block_address = (offset_t) -1;
4
#if SD_RAW_WRITE_BUFFERING
5
    raw_block_written = 1;
6
#endif
7
    if(!sd_raw_read(0, raw_block, sizeof(raw_block)))
8
        return 0;
9
#endif
Und bleibt bei sd_raw_read(...) hängen(!). Hab schon mal hier in dem 
Thread ein wenig gesucht, scheint aber ein unbekanntes Problem zu sein? 
Ich werde die Sache noch mal weiter verfolgen.

Innerhalb von sd_raw_read bleibt es hier hängen:
1
            /* wait for data block (start byte 0xfe) */
2
            while(sd_raw_rec_byte() != 0xfe);

Und zwar, weil die Karte 0xFF zurückgibt. Na sowas.

Es werden keine Pegelwandler verwendet, das ganze System läuft auf 3,3V. 
Zum Einsatz kommt eine µSD Karte von extrememory.

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Simon,

Simon K. wrote:
> Eine Anmerkung und eine Frage:
>
1
> void sd_raw_send_byte(uint8_t b)
2
> {
3
>     SPDR = b;
4
>     /* wait for byte to be shifted out */
5
>     while(!(SPSR & (1 << SPIF)));
6
>     SPSR &= ~(1 << SPIF);
7
> }
8
>
>
> Die Zeile SPSR &= ~(1<<SPIF); ist imho a) Quatsch und b) unnötig. a)
> Löscht man ein Interrupt Flag durch Schreiben einer 1 an der Stelle und
> b) SPIF wird automatisch gelöscht, wenn SPSR mit gesetztem SPIF gelesen
> wurde.

Danke für die Anregung. Ich werd mir das mal ansehen. Eventuell ist es 
bei gewissen Reihenfolgen von sd_raw_send_byte()/sd_raw_rec_byte() 
notwendig, so genau weiß ich das nicht mehr.

> Ich habe aber Probleme die ganze Library in ein Projekt einzubinden, wo
> an der SPI Schnittstelle auch noch ein ENC28J60 hängt. [...]
>
> Eventuell hast du noch eine Idee welche Aktionen aus deiner Library mit
> einer anderen SPI Library kollidieren könnten.

Schau Dir mal mega-eth unter
  http://www.roland-riegel.de/mega-eth/
an, dort habe ich genau dieses Problem durch ein kleines zusätzliches 
SPI-Interface gelöst.

> Innerhalb von sd_raw_read bleibt es hier hängen:
1
>            /* wait for data block (start byte 0xfe) */
2
>            while(sd_raw_rec_byte() != 0xfe);

Vermutlich stört da der ENC28J60 irgendwie. Wie schon gesagt, schau Dir 
mal meine obige Lösung an.

Gruß,
Roland

von Simon K. (simon) Benutzerseite


Lesenswert?

niketchana wrote:
> Hallo,
> jetzt geht´s. Das war ein Problem der Formatierung.Anscheinend
> formatiert Window mit FAT12.Ich habe die Karte mit dem "SD Formatter
> 2.0.0.3 von Panasonic" formatiert und schon geht alles.
> niketchana

Hi Roland,
Danke für den Tipp mit dem mega-eth. Das Problem ist doch schon mal 
aufgetreten in diesem Thread und somit ließ sich eine Lösung finden.

Jetzt bleibt er wenigstens nicht hängen.

von Roland R. (roland) Benutzerseite


Lesenswert?

Servus Thorsten,

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

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

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

Viele Grüße,
Roland

von Thorsten S. (Gast)


Lesenswert?

Hallo Roland,

nachdem ich FAT_WRITE_SUPPORT auch auf 1 gesetzt habe, bekomme ich 
Zugriff auf die Karte :-) (Obwohl ich doch nur lesen wollte)

Vielen Dank für die Hilfe (verneig) !
Thorsten

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Thorsten,

Schön, dass es jetzt wieder funktioniert.

Wenn Du insgesamt nur Leseunterstützung brauchst, kannst Du natürlich 
beides (FAT_WRITE_SUPPORT und SD_RAW_WRITE_SUPPORT) auf 0 setzen.

fat_open() überprüft die Funktionsargumente, und wenn 
FAT-Schreibunterstützung aktiviert wurde, jedoch keine Funktionszeiger 
zum Schreiben auf den Datenträger übergeben werden, endet fat_open() mit 
einem Fehler.

Gruß,
Roland

von Simon K. (simon) Benutzerseite


Lesenswert?

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

von Thorsten S. (Gast)


Lesenswert?

Ich hatte den Write-Support auf 1, aber vergessen in der fat.h auch den 
write-support zu setzen.
Vielleicht kannst Du die Doku etwas ändern, damit man auf diese 
Abhängigkeit etwas hingewiesen wird.

von Roland R. (roland) Benutzerseite


Lesenswert?

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

Sehr schön :)

@Thorsten
> Vielleicht kannst Du die Doku etwas ändern, damit man auf diese
> Abhängigkeit etwas hingewiesen wird.

Ich werde mir was überlegen.

Gruß,
Roland

von Jan (Gast)


Lesenswert?

Hallo Roland, vielen Dank für deine Hinweise,

> Was genau hast Du wo herumgebastelt? Was funktioniert nicht mehr? Was
> soll funktionieren? Was passiert stattdessen (oder eben nicht)?

Hier ist das Problem: Ich weiß leider nicht mehr was ich verändert habe. 
Ich konnte vorm "rumbasteln" eine Datei öffnen und etwas in die Datei 
schreiben. Jetzt kann ich zwar die Datei öffnen und lesen, aber nicht 
mehr beschreiben. Ich gebe mir Debuginfromationen über die Konsole aus 
und danach müsste eigentlich auch alles klappen. Hier nochmal eine 
veränderte Version meines Codes:
1
 if(!partition)
2
        {
3
            /* If the partition did not open, assume the storage device
4
             * is a "superfloppy", i.e. has no MBR.
5
             */
6
            partition = partition_open(sd_raw_read,
7
                                       sd_raw_read_interval,
8
                                       sd_raw_write,
9
                                       sd_raw_write_interval,
10
11
                                       -1
12
                                      );
13
            if(!partition)
14
            {
15
16
                uart_puts_p(PSTR("opening partition failed\n"));
17
18
                continue;
19
            }
20
      else
21
      {
22
        uart_puts_p(PSTR("partition open \n"));
23
        
24
      }
25
        }
26
27
    else
28
    {
29
30
      uart_puts_p(PSTR("partition open \n"));
31
32
          /* open file system */
33
          struct fat_fs_struct* fs = fat_open(partition);
34
          if(!fs)
35
          {
36
37
              uart_puts_p(PSTR("opening filesystem failed\n"));
38
39
              continue;
40
          }
41
      else
42
      {
43
        uart_puts_p(PSTR("filesystem open \n"));
44
45
46
            /* open root directory */
47
            struct fat_dir_entry_struct directory;
48
49
50
            if(fat_get_dir_entry_of_path(fs, "/test", &directory))
51
        {
52
          uart_puts_p(PSTR("fat_get_dir_entry_of_path\n"));
53
      
54
55
              struct fat_dir_struct* dd = fat_open_dir(fs, &directory);
56
              if(!dd)
57
              {
58
59
                  uart_puts_p(PSTR("opening root directory failed\n"));
60
              }
61
          else
62
          {
63
64
            uart_puts_p(PSTR("Filesystem open \n"));
65
    
66
  
67
         
68
69
70
            uart_puts("\n");
71
72
            while(fat_read_dir(dd, &directory))
73
              {
74
                    if(strcmp(directory.long_name, "test.txt") == 0)
75
                    {
76
          
77
                uart_puts("found test.txt \n");
78
                uart_puts(directory.long_name);
79
                uart_puts("\n");
80
81
                struct fat_file_struct * file = fat_open_file(fs,&directory);
82
                
83
                if(!file)
84
                {
85
                  uart_puts_p(PSTR("file error\n"));
86
                }
87
                else
88
                {
89
                  uart_puts_p(PSTR("file ok\n"));
90
91
                  char write[] = "test";
92
  
93
                  int data_len = strlen(write);
94
95
96
                  if(fat_write_file(file, (uint8_t*) write, data_len) != data_len)
97
                      {
98
                          uart_puts_p(PSTR("error writing to file\n"));
99
                    break;
100
      
101
  
102
                      }
103
                  else
104
                  {
105
                    uart_puts("file beschrieben \n");
106
                    fat_close_file (file);
107
                    break;
108
                  }
109
110
  
111
                }
112
                 
113
                break;   
114
                   }
115
              
116
117
              }
118
119
          }
120
        }
121
        
122
      }
123
       
124
    }
125
        
126
127
    break;

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Jan,

> Hier ist das Problem: Ich weiß leider nicht mehr was ich verändert habe.

Das ist immer schlecht. Wie willst Du da wissen, durch welche Änderungen 
die auftretenden Fehler verursacht werden? Schon mal über die Verwendung 
einer Versionsverwaltung nachgedacht?

> Jetzt kann ich zwar die Datei öffnen und lesen, aber nicht
> mehr beschreiben. Ich gebe mir Debuginfromationen über die Konsole aus
> und danach müsste eigentlich auch alles klappen.

Du meinst also, die Aufrufe geben alle keinen Fehler zurück, obwohl die 
Daten nicht in der Datei landen? Hast Du vielleicht vor dem Abziehen der 
Karte ein sd_raw_sync() vergessen?

> Hier nochmal eine veränderte Version meines Codes:

Hänge lange Quelltexte bitte als Datei an Dein Posting an. Das würde die 
Übersichtlichkeit sehr steigern und hoffentlich auch der 
Code-Formatierung zugute kommen.

Viele Grüße,
Roland

von Jan (Gast)


Lesenswert?

Hallo Roland,

> Das ist immer schlecht. Wie willst Du da wissen, durch welche Änderungen
> die auftretenden Fehler verursacht werden? Schon mal über die Verwendung
> einer Versionsverwaltung nachgedacht?

ich war wohl auf Anhieb so begeistert, das sowohl Hardware als auch 
Software funktionieren, dass ich vom funktionierenden Quellcode kein 
Backup gemacht habe.
Ich habe den Fehler gefunden. Ich hab beim "rumbasteln" wohl die 
sd_raw_sync() Funktion gelöscht. Jetzt funktioniert alles einwandfrei. 
Vielen Dank für deine Hilfe und den tollen Quellcode

von Jan (Gast)


Lesenswert?

Nachdem bei meinem Atmega32 alles funktioniert hat, wollte ich den 
SD-Reader an ein AT90CAN128 anschließen. Im Vergleich zum Atmega32 hat 
dieser 8MHz statt 14,..Mhz

Im Code habe ich F_CPU und die Ports abgeändert.

Jetzt tauchen folgende Probleme auf.

Die Karte wird nicht immer auf Anhieb erkannt, erst nach einem Reset.
Ich erstelle mehrere Files, aber es scheint, dass die sd_raw_sync() 
nicht immer korrekt ausgeführt wird. Erst nach ein paar Resets, befinden 
sich die Daten auch auf der Karte.

Hat jemand schonmal dieses Problem gehabt?

von Uwe B. (boerge) Benutzerseite


Lesenswert?

MoinMoin,

kann es sein, dass die letzten Versionen SRAM-Probleme bei einem Mega168 
verursachen? In meinem Programm funktioniert alles hervorragend bis dann 
fat_create_file (und dort drin speziell fat_read_dir) aufgerufen wird. 
Der Mega resettet sich in dem Augenblick...

Bis auf das Pinning habe ich eigentlich alle Einstellungen in den 
Headerfiles so belassen, wie im Orginal.

Hat es jemand auf einem Mega168 am laufen?

Uwe

von Uwe B. (boerge) Benutzerseite


Lesenswert?

MoinMoin,

habe mir gerade den Thread in Ruhe durchgelesen (war gestern abend nach 
endlosen Probieren zu spät dafür...) und gesehen, dass es scheinbar 
wirklich ein SRAM-Problem auf dem Mega168 sein wird. An dem Board, mit 
welchem ich gerade rumexperimentiere, ist noch ein LCD via TWI 
abgeschlossen, dafür aber kein UART ...

Hmm, gibt es eine Möglichkeit mit ein paar Einstellungen den 
SRAM-Verbrauch ein wenig zu minimieren, um doch Rolands Routinen auf 
einem Mega168 zu verwenden. Ziel ist es eigentlich einen kleinen 
Datenlogger (Datenquellen via TWI eingebunden) aufzubauen.

Grüße & Danke Uwe

von Gast (Gast)


Lesenswert?

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

von Uwe B. (boerge) Benutzerseite


Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

@Jan
> Die Karte wird nicht immer auf Anhieb erkannt, erst nach einem Reset.

Stabile Spannungsversorgung? Ausreichende Leistung?

> Ich erstelle mehrere Files, aber es scheint, dass die sd_raw_sync()
> nicht immer korrekt ausgeführt wird. Erst nach ein paar Resets, befinden
> sich die Daten auch auf der Karte.

Treten Fehler auf? Wenn ja welche? Wird der Controller plötzlich neu 
gestartet?

@Uwe
> kann es sein, dass die letzten Versionen SRAM-Probleme bei einem Mega168
> verursachen? In meinem Programm funktioniert alles hervorragend bis dann
> fat_create_file (und dort drin speziell fat_read_dir) aufgerufen wird.
> Der Mega resettet sich in dem Augenblick...

Könnte durchaus sein, zumal fat_read_dir() ziemlich Stack-intensiv ist. 
Falls der "init"-Befehl benutzt wird, gibt es in der aktuellen Version 
auch noch ein kleines Speicherleck.

Zugegebenerweise habe ich die letzten Releases nicht mehr explizit auf 
einem mega168 getestet. Mittlerweile betrachte ich das ganze als 
Universal-Library, die nicht mehr an eine bestimmte MCU gebunden ist.

Möglichkeiten zur RAM-Verbrauchsminimierung:
- FAT32/SDHC ausschalten
- FAT_FS_COUNT, FAT_FILE_COUNT, FAT_DIR_COUNT minimieren
- Länge von fat_dir_entry_struct.long_name reduzieren
- Länge des Befehlszeilenpuffers reduzieren (main.c, ca. Zeile 295)
- Beispielprogramm abspecken
- LFN-Unterstützung abschalten (erst im nächsten Release)

Viele Grüße,
Roland

von Sucher (Gast)


Lesenswert?

Hallo SD-Karten User von RR,

es haben ja schon einige einen Datenlogger gebaut. Ich möchte mit einem 
Atmega644 von der seriellen Schnitstelle von einem GPS Modul eine 
kontinuierliche Sequenz auf die SD Karte loggen. Wie macht man das am 
geschicktesten, dass die Karte eine lange lebensdauer hat?

...Am Anfang einen entsprechend grossen File erzeugen
...while (512K voll) dann schreiben...
...nur 512K Blöcke schreiben?
...sd_raw_sync()
...bei erreichen vom File Ende ==> Neuen File allokieren?
...???????

Könnte bitte jemand seinen funktionierende (Dauer)-Logger Anwendung 
einstellen?

MfG
Achim

von Torsten S. (tse)


Lesenswert?

Roland Riegel schrieb:

> Könnte durchaus sein, zumal fat_read_dir() ziemlich Stack-intensiv ist.
> Falls der "init"-Befehl benutzt wird, gibt es in der aktuellen Version
> auch noch ein kleines Speicherleck.

Huch, jetzt machst Du mir aber richtig Angst. Ich benutze die vorletzte 
Version seit einigen Wochen im Dauereinsatz. Gilt das dort auch, und 
welches "init" meinst Du, etwa sd_raw_init()?

Mit einem Dragon habe ich mir den SRam via JTAG auf dem Mega128 mehrmals 
in der Testphase angeguckt. Das komplette SRam beim Reset mit einem 
Bytemuster beschrieben, ein paar Stunden laufen lassen, dann nochmal 
nachgeschaut. Da waren immer locker 2k frei.

Es gab(gibt) einige Auffälligkeiten, die ich meinem eigenen Zeugs 
zugeordnet hatte aber nie richtig erkären konnte. Wenn Du möchtest, 
versuche ich der Sache nochmals tiefer auf den Grund zu gehen.

Torsten

von Jan (Gast)


Lesenswert?

Die Spannungsversorgung ist stabil und die Leistung müsste auch 
ausreichend sein.
Beim Debuggen gibt es keine Fehlermeldungen. Alles scheint ganz normal 
zu sein, nur das sich nachher keine Daten auf der Karte befinden, bzw. 
nur ab und zu die Daten gespeichert werden.
Ich gebe mal davon aus, dass zumindest die Hardware in Ordnung ist, denn 
mit einem anderen SD-Kartenprojekt funktioniert alles einwandfrei.

Rein theoretisch hätte es ja reichen müssen, FCPU und die Ports zu 
ändern.

von Roland R. (roland) Benutzerseite


Lesenswert?

@Torsten
> welches "init" meinst Du, etwa sd_raw_init()?

Den Befehl der UART-Kommandozeile aus main.c. Das Verzeichnis-Handle 
wird bei "init" nicht geschlossen.

> Mit einem Dragon habe ich mir den SRam via JTAG auf dem Mega128 mehrmals
> in der Testphase angeguckt. Das komplette SRam beim Reset mit einem
> Bytemuster beschrieben, ein paar Stunden laufen lassen, dann nochmal
> nachgeschaut. Da waren immer locker 2k frei.

Mit nem ATmega128 ist das auch kein Problem. Nur die 1k von den 
mega8/88/168 sind halt recht knapp. Der Code selbst sollte mittlerweile 
ziemlich ausgereift sein.

> Es gab(gibt) einige Auffälligkeiten, die ich meinem eigenen Zeugs
> zugeordnet hatte aber nie richtig erkären konnte. Wenn Du möchtest,
> versuche ich der Sache nochmals tiefer auf den Grund zu gehen.

Wenn Du möchtest, gerne. Gehöre mittlerweile aber nicht mehr den 
Studenten an, deshalb ist die Zeit eher begrenzt.

@Jan
> Ich gebe mal davon aus, dass zumindest die Hardware in Ordnung ist, denn
> mit einem anderen SD-Kartenprojekt funktioniert alles einwandfrei.

Wieso gehst Du davon aus, dass die Hardware in Ordnung ist, wenn die 
Software nahezu die gleiche geblieben ist, es aber bei der einen 
Hardware funktioniert und bei der anderen nicht? Schon mal mit mehreren 
Karten probiert?

Grüße,
Roland

von Sucher (Gast)


Lesenswert?

Hallo
ich möchte diesen Thread nicht verwässen und habe deshalb einen neuen 
Thread gestartet.
Wie sieht es mit der Lebensdauer der Karte aus, wenn man pro Sekeunde 
kleine Einheiten schreibt?
Ist das unsinnig?
Wie sollte man da vorgehen?

MfG
Achim

siehe ==>Beitrag "SD Card GPS Logger optimieren?"

von Vladimir (Gast)


Lesenswert?

Hallo Herr Riegel,danke für Ihre Librarys. In Ihrem Beitrag steht, dass 
Sie die Beschreibung des Mini-Shells geschrieben haben. Leider kann ich 
die weder auf Ihrer Seite noch in der beigefügten Dateien finden. Ich 
werde mich sehr freuen, wenn Sie mir einen Hinweis geben, wo sie zu 
finden ist.

MFG

Vladimir

von Joachim (Gast)


Lesenswert?

Hallo,
Ich habe die aktuelle Version auf einen ARM7 von Atmel portiert.
Läuft fast alles, FAT16, FAT32 und auch SDHC Karten werden problemlos 
erkannt.
Ein einziges Problem kann ich nicht nachvollziehen:
Legt man eine neue Datei an (so dass im Verzeichnis die Clusterposition 
noch auf Null steht) und versucht dann, in diese zu schreiben, so stürzt 
der Kontroller ab. Soweit ich herausgefunden habe, im Moment des 
"Return" der SPI-Schreibroutine. Dabei ist es unabhängig davon, ob FAT16 
oder FAT32 benutzt wird.
Vorgehensweise: "touch datei.txt" ->OK, "sync"->OK, "write datei.txt 0" 
-> "< Texteingabe+Enter" -> Absturz.
Nach Neustart ist die Datei weiterhin leer und es wurde kein 
Startcluster im Verzeichnis angelegt.
Liegt bereits eine Datei mit Inhalt vor, dann kann diese problemlos 
beschreiben bzw. geändert werden.

Die Frage ist, hat das schon jemand mit AVR erfolgreich getestet?
Bin mir nicht sicher, ob es ein Bug ist, oder ob es an der Portierung 
auf den ARM (wg. 32Bit Architektur) liegt. Da aber alle anderen 
Funktionen gehen, tippe ich eher auf einen Bug.

Danke und Gruß

Joachim

von Roland R. (roland) Benutzerseite


Lesenswert?

Joachim schrieb:
> Soweit ich herausgefunden habe, im Moment des
> "Return" der SPI-Schreibroutine.

Sehr unwahrscheinlich, dass das ein Fehler in der Library ist. Die 
SPI-Schreibroutine ist hardwareabhängig und damit wohl von Dir 
abgeändert worden. Zudem spricht ein Absturz beim return stark für einen 
Pufferüberlauf auf dem Stack.

Gruß,
Roland

von Joachim (Gast)


Lesenswert?

Hi Roland,

Vielen Dank für die Antwort.
Ja, die SPI-Routine ist natürlich für den ARM7 umgeschreiben. 
Funktioniert ja auch, außer in diesem einen Fall beim Schreiben einer 
leeren Datei.
Stacküberlauf schließe ich mal nicht aus. Daran dachte ich auch schon.
Wollte nur sichergehen, dass ich nicht am falschen Ende suche.
Zwar gehe ich davon aus, dass der ARM mehr Stack zur Verfügung hat als 
ein ATMEGA, weil 64K RAM, aber vielleicht habe ich was in der Startup.c 
übersehen. Muss ich mal untersuchen.

Gruß

Joachim

von Dschadu (Gast)


Lesenswert?

Hi,
ich bin schon seit Tagen am versuchen eine SD-Karte zu beschreiben, ohne 
erfolg :(
Mein Schaltkreis ist folgender: http://bildupload.sro.at/p/328495.html
Wie man sieht, nutze ich einen Mega32. Das alles habe ich auf eine 
eigene Platine geätzt - Verbindungen bestehen alle, daran liegt es also 
nicht. Spannungen sind exakt 5V und an der SD-Karte 3,32V. Daher geh ich 
davon aus, das es Software-seitig ein Problem gibt.
Folgende main.c hab ich geschrieben:
http://darki89.bplaced.net/files/main.txt
Im grunde besteht die Datei aus zusammenkopierten Teilen der 
Beispieldatei. Jedoch scheitert der Controller bereits an der Stelle wo 
die Partition geöffnet werden soll, die LED (fehleranzeige) geht an. Die 
Abfrage auf den Schreibschutz der Karte habe ich geändert, da der 
Schieber an der Karte leider fehlt:
#define configure_pin_available()
#define configure_pin_locked()

#define get_pin_available() 0
#define get_pin_locked() 0

Außerderm habe ich SD_RAW_WRITE_SUPPORT auf 1.
Fat32 und SDHC habe ich aus. Als Karte verwende ich eine alte 64MB FAT 
formatierte karte, mit einer Zuordnungsgröße von 4096Byte.

Ich hab den Thread hier schon ein wenig durchforstet und versucht, die 
Zeilen mit der maximalen SD-Geschwindigkeit auszukommentieren, brachte 
keine Besserung. Die Sache mit dem Schreibschutz, was ich auch hier 
gefunden hab, habe ich oben ja schon erwähnt. Mehr sachen habe ich 
leider nicht finden können, da der Thread einfach verdammt groß ist.
Hat jemand eine Idee? Leider habe ich kein Debug-Interface wie JTAG oder 
was über RS232 (hab so nen anschluss garnichmehr).
Danke schonmal :)

von geb (Gast)


Lesenswert?

@Dschadu

Versuch doch mal erst die rudimentären Funktionen wie sektor schreiben 
und lesen zu testen. Schreib z.B. eindach einen Textstring auf ein paar 
100 Sektoren, lies sie dann und vergleiche. Das muß bis aufs letzte Bit 
stimmen, bevor du da ein Filesystem verwenden kannst.
Um eine serielle Schnittstelle zu debug-Zwecken (mit printf o.ä.) wirst 
du da nicht herumkommen.
p.s. Ich hab 2Wochen mit meinem ADUC7024 gekämpft bis alles gut gelaufen 
ist.
Grüße Gebhard

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Dschadu,

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

Dann sollte es auch mit dem Schreiben funktionieren...

Gruß,
Roland

von Matze (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
erst ein mal großes Lob, denn der Code tut einbahnfrei.
Allerdings nur solange ich dein Bsp. Programm nutze.

Ich vermisse Methoden die den ganzen Kram machen den du direkt in der 
main() machst
also etwas in diese richtung:
1
uint8_t sd_init();
2
void   sd_ende();
3
uint8_t sd_write(char* file, char* data, uint8_t length, uint32_t pos, uint8_t whence);
4
uint8_t sd_read(char* file, char* erg, uint8_t length, uint8_t max_length, uint32_t pos, uint8_t whence);
5
uint8_t sd_cd(char* dir);
6
uint8_t sd_deletfile(char* file);
7
uint8_t sd_creatfile(char* file);
8
uint8_t sd_creatdir(char* dir);
9
uint8_t sd_print_disk_info();
Sodass ich nur diese Methoden brauche.

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

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

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

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

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

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

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

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

gruß
Matze

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Matze,

Matze schrieb:
> Ich vermisse Methoden die den ganzen Kram machen den du direkt in der
> main() machst
> also etwas in diese richtung:
> [...]
> Sodass ich nur diese Methoden brauche.
>
> Ich versuche jetzt schon seit mehr als 2 Woche etwas dergleichen zu
> machen. Klappt leider nicht.

Was genau klappt denn nicht?

Die von Dir gewünschten Funktionen sollten aus den bereits vorhandenen 
relativ schnell implementiert werden können. Generell sollte Dir aber 
bewusst sein, dass bei jedem Aufruf der von Dir skizzierten Funktionen 
z.B. die Dateien neu geöffnet und geschlossen werden müssen, was einiges 
an Overhead bedeutet sowie Performance und Flexibilität nimmt.

> Zu den Fehlern:
> es wird nur am Uart nur "Start" und "init" ausgegeben dies allerding
> ständig der macht also irgendwo im init teil nen reset.
>
> Wenn ich allerdings die Schleife while(idle) -sammt Inhalt-
> auskommentiere dann initialisiert er ganz normal und gibt mir die Disk
> Info aus.
>
> Ich hab dann mal noch verschiedene sachen ausprobiert mit if oder mit
> weniger schleifen ... jedesmal kam was anderes raus. aber nie das was
> sollte.
>
> Diese fehler lassen darauf schließen, dass der Compiler misst macht. Und
> das gefällt mir garnicht!

Nein, der Compiler ist höchstwahrscheinlich unschuldig.

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

Der ATmega168 ist ziemlich knapp bemessen, vor allem bzgl. verfügbarem 
RAM. Du hast zu Beginn von main() einige neue Variablen eingeführt, die 
insgesamt ca. 60 Bytes benötigen. Das ist verhältnismäßig viel und 
könnte zur Kollision von Stack und Heap führen, wodurch allerhand 
undefinierte und merkwürdige Sachen zustande kommen. Siehe dazu auch die 
letzte FAQ unter http://www.roland-riegel.de/sd-reader/faq/

Reduziere mal testweise den Funktionsumfang in main() und überprüfe die 
Konfigurationen in sd-raw_config.h und fat_config.h. Schalte SDHC, 
FAT32, Zeitstempel und zur Not auch Schreibzugriff aus, und teste 
erstmal damit.

Gruß,
Roland

von Thomas (Gast)


Lesenswert?

Hallo zusammen,

ich habe mir den Beitrag hier duchgelesen.
Jedoch habe aber immer noch eine Frage, die mich beschäftigt.

So wie ich es verstanden habe, ist für die Unterstützung der 
FAT-Routinen eine SD-Karte nötig, die mit einer Blockgröße von 512 Byte 
formatiert ist.

Ist es möglich, mit einem Atmel Mikrocontroller eine angeschlossene 
SD-Karte derart zu formatieren?

Wenn ja, wie wird es umgesetzt?


Mit freundlichen Grüßen
Thomas

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Thomas,

> So wie ich es verstanden habe, ist für die Unterstützung der
> FAT-Routinen eine SD-Karte nötig, die mit einer Blockgröße von 512 Byte
> formatiert ist.

Nein. Die Blockgröße von 512 Bytes hat nichts mit FAT zu tun. Es geht 
dabei um die Blöcke, mit der die SD-Karten angesteuert werden.

Den Karten ist es egal, mit welchem Dateisystem die Daten verwaltet 
werden. Du kannst also beliebig erstellte FAT-Dateisysteme verwenden, 
mit beliebiger Clustergröße ("Cluster" -> FAT16/32, "Block" -> 
Datenträger).

Gruß,
Roland

von Thomas (Gast)


Lesenswert?

Hallo Roland,

ok dann habe ich das mit der Blockgröße missverstanden.

Aber ist es nicht so, das ich eine SD-Karte unter Windows nur mit 
bestimmten Clustergrößen formatieren kann.

Um aber mit einem Amtel-Controller die FAT zu realisieren, wird so weit 
ich weis, meistens die Clustergröße von 512 Byte verwendet. So kann dann 
ein gelesener Cluster direkt ins RAM geschrieben werden.
OK, mit einem entsprechenden Controller kann man auch Cluster von 1024 
Byte lesen und im RAM puffern, aber z. B. mit einem ATmega16 ist das 
nicht möglich.

Wenn dem so ist, muss diese SD-Karte ja dementsprechend (Clustergröße 
von 512 Byte) formatiert werden.

Ist dieses formatieren denn auch mit einen Atmel-Controller 
realisierbar?
Also kann ich mir das formatieren der Karte am PC durch eine Funktion im 
Mikrocontroller ersetzen?

Wenn ja, wie wird es umgesetzt?


Mit freundlichen Grüßen
Thomas

von Roland R. (roland) Benutzerseite


Lesenswert?

Servus Thomas,

Thomas schrieb:
> Aber ist es nicht so, das ich eine SD-Karte unter Windows nur mit
> bestimmten Clustergrößen formatieren kann.

Jein. Die Clustergröße wird automatisch so gewählt, dass mit den max. 
ca. 65000 Clustern von FAT16 der ganze Datenträger abgedeckt werden 
kann.

> Um aber mit einem Amtel-Controller die FAT zu realisieren, wird so weit
> ich weis, meistens die Clustergröße von 512 Byte verwendet.

Nein. Sonst könntest Du, wie oben angedeutet, mit FAT16 nur maximal ca. 
32MB verwalten.

> So kann dann
> ein gelesener Cluster direkt ins RAM geschrieben werden.
> OK, mit einem entsprechenden Controller kann man auch Cluster von 1024
> Byte lesen und im RAM puffern, aber z. B. mit einem ATmega16 ist das
> nicht möglich.

Doch. Es sagt ja niemand, dass man immer einen ganzen Cluster einlesen 
muss. Bei den SD-Karten wird zwar immer ein ganzer Block (512 Bytes) 
eingelesen, aber es ist egal, ob das nun ein ganzer Cluster ist oder 
nicht.

> Wenn dem so ist, muss diese SD-Karte ja dementsprechend (Clustergröße
> von 512 Byte) formatiert werden.

Dem ist nicht so. Das Cluster-Prinzip ist eine Abstraktion des 
Dateisystems, nicht des Kartenzugriffs.

> Ist dieses formatieren denn auch mit einen Atmel-Controller
> realisierbar?

Theoretisch wohl schon, mit meiner Bibliothek aber nicht.

> Also kann ich mir das formatieren der Karte am PC durch eine Funktion im
> Mikrocontroller ersetzen?

S.o. Generell würde ich aber sagen, dass das Formatieren am PC einfacher 
ist und Code auf dem Mikrocontroller spart.

> Wenn ja, wie wird es umgesetzt?

Naja, mann müsste eben entsprechende Header-Informationen und mind. eine 
FAT an den Anfang der Partition schreiben und ein Wurzelverzeichnis 
anlegen.

Gruß,
Roland

von Lowtzow .. (lowtzow)


Lesenswert?

hallo

wollten den neuesten code 2009-03-30 von roland rieger in avr studio 
4.14 für einen mega328p compilieren.
es kommt dann folgende fehlermeldung: ../sd_raw_config.h:107:6: error: 
#error "no sd/mmc pin mapping available!"

ich denke der fehler liegt daran, dass ich im avr studio nur den 
mega328p (den mega328 gibt es nicht) auswählen kann jedoch im programm 
der mega328 definiert ist. wenn ich defined(_AVR_ATmega328_) auf 
defined(_AVR_ATmega328P_)  ändere bekomme ich jedoch fehlermeldungen 
wie
zb
../sd_raw.c:184: error: 'PB2' undeclared (first use in this function)
../sd_raw.c:184: error: (Each undeclared identifier is reported only 
once
../sd_raw.c:184: error: for each function it appears in.)
../sd_raw.c: In function 'sd_raw_available':
../sd_raw.c:341: error: 'PC4' undeclared (first use in this function)
../sd_raw.c: In function 'sd_raw_locked':
../sd_raw.c:352: error: 'PC5' undeclared (first use in this function)
../sd_raw.c: In function 'sd_raw_read':
../sd_raw.c:467: error: 'PB2' undeclared (first use in this function)
../sd_raw.c: In function 'sd_raw_write':
../sd_raw.c:714: error: 'PB2' undeclared (first use in this function)
../sd_raw.c: In function 'sd_raw_get_info':
../sd_raw.c:858: error: 'PB2' undeclared (first use in this function)
make: *** [sd_raw.o] Error 1
Build failed with 8 errors and 0 warnings...

kann vielleicht jemand helfen?!

WinAVR-20080610 (AVR Libc 1.6.2 )
avrstudio 4.14 verwende ich

mfg

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

Lowtzow .... schrieb:
> wollten den neuesten code 2009-03-30 von roland rieger in avr studio
> 4.14 für einen mega328p compilieren.
> es kommt dann folgende fehlermeldung: ../sd_raw_config.h:107:6: error:
> #error "no sd/mmc pin mapping available!"
>
> ich denke der fehler liegt daran, dass ich im avr studio nur den
> mega328p (den mega328 gibt es nicht) auswählen kann jedoch im programm
> der mega328 definiert ist. wenn ich defined(_AVR_ATmega328_) auf
> defined(_AVR_ATmega328P_)  ändere bekomme ich jedoch fehlermeldungen

Die Unterstützung für den mega328 ist im aktuellen Release versaut. Da 
war ich etwas vorschnell, tut mir Leid.

Nach dem Anwenden des Patches im Anhang sollte es funktionieren.

Gruß,
Roland

von Pete K. (pete77)


Lesenswert?

Hallo Roland,

in Deinem aktuellen Schaltplan werden CD und WP mit Pullup gegen VCC 
(=5V) gezogen. Ist das so richtig, oder sollten es nicht 3.3V sein?

Gruss,
Pete

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Pete,

Ja das ist korrekt, denn CD und WP sind ja nur Kontakte des 
Kartenhalters, damit der uC erkennen kann, ob eine Karte gesteckt ist 
und ob deren Schreibschutzschalter aktiv ist.

Falls Dein Sockel diese Kontakte nicht hat, bitte den Code so abändern 
wie in der FAQ auf meiner Homepage beschrieben.

Gruß,
Roland

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

Hallo zusammen!

Nach längerer Zeit habe ich mal wieder ein neues sd-reader-Release 
erstellt (siehe Anhang). Neben Bugfixes enthält es auch zwei neue 
Features.

- Optional verzögerte Aktualisierung von Verzeichniseinträgen.
  Dies kann die Schreib-Performance in vielen Szenarios erhöhen.
- Unterstützung für lange Dateinamen (LFN) ist jetzt abschaltbar.
- Ignoriere LFN-Einträge ohne zugehörigen 8.3-Namen.
- Ignoriere LFN-Einträge, welche nicht zur 8.3-Prüfsumme passen.
- Beschleunigung der Suche nach einem freien Cluster (in einigen
  Fällen).
- Speicherleck beim Uart-Kommando "init" behoben.
- Korrektur der ATmega328P-Pinzuordnungen, andere AVR
  picoPower-Varianten hinzugefügt.

Den zugehörigen Patch, andere Einzelheiten, FAQs, neue Benchmarks mit 
verzögert aktualisierten Verzeichniseinträgen und Dokumentation gibts 
wie immer auf meiner Homepage:
  http://www.roland-riegel.de/sd-reader/

Viele Grüße,
Roland

von Hannes (Gast)


Lesenswert?

Hallo Roland,

zuerst mal ein fettes danke für deine arbeit! hammer!!!!

ich hätte jedoch eine frage:

wenn ich ein file erstelle und darin messwerte abspeichere erkennt er 
mir kein enter

zb.:

2010-01-10 12:32:11;14,532;l/s;29328398.2938;m3<ENTER>
2010-01-10 12:32:12;14,532;l/s;29328398.2938;m3<ENTER>
2010-01-10 12:32:13;14,532;l/s;29328398.2938;m3<ENTER>
2010-01-10 12:32:14;14,532;l/s;29328398.2938;m3<ENTER>
2010-01-10 12:32:15;14,532;l/s;29328398.2938;m3<ENTER>
2010-01-10 12:32:16;14,532;l/s;29328398.2938;m3<ENTER>

ich habe zwar einen code hinzugefügt das er mir bei einem # Zeichen ein 
Enter durchführt. es wäre vielleicht gut dies in einem code zu 
implementieren oder gibt es schon sowas und ich habs überlesesn.

lg
hannes

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Hannes,

Hannes schrieb:
> wenn ich ein file erstelle und darin messwerte abspeichere erkennt er
> mir kein enter

Meinst Du den "write"-Befehl auf der UART-Kommandozeile? Das stimmt, der 
schreibt keine Zeilenumbrüche. Aber er ist ja auch nicht dafür gedacht, 
von einer realen Anwendung verwendet zu werden. Aber wenn Du es 
unbedingt brauchst, kannst Du die Implementierung in main.c ja 
entsprechend abändern.

Gruß,
Roland

von Hannes (Gast)


Lesenswert?

danke roland für deine antwort.

schon mal an den ernstfall gedacht wenn unterm schreiben die spannung 
einbricht (gerade im akku oder batterie betrieb von einem gerät mit 
deiner software) ?
was ich immer bei fat etc. datenspeicherung bedenke, gerade im batterie 
betrieb, das das system crasht

vielleicht kannst du mir was dazu sagen

Viele Grüße
Hannes

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Hannes,

Hannes schrieb:
> schon mal an den ernstfall gedacht wenn unterm schreiben die spannung
> einbricht (gerade im akku oder batterie betrieb von einem gerät mit
> deiner software) ?
> was ich immer bei fat etc. datenspeicherung bedenke, gerade im batterie
> betrieb, das das system crasht
>
> vielleicht kannst du mir was dazu sagen

Nun ja, was soll ich da von Seiten der Library noch groß tun? Gegen 
einen Ausfall der Spannungsversorgung kann man nichts machen, das ist 
aber bei allen Dateisystemen so. Natürlich gibt es Journaling-Systeme, 
die nach einem Crash das System möglichst schnell wieder herstellen, 
gegen einen Datenverlust schützen sie aber auch nicht.

Bei meiner Library habe ich zwar darauf geachtet, dass nur zu möglichst 
wenigen und möglichst kurzen Zeitpunkten das Dateisystem inkonsistent 
wäre. Aber auch das bewahrt nicht vor Datenverlust.

Allerdings ist ja im Falle von batteriebetriebenen Geräten nicht von 
einem plötzlichen Spannungsausfall, sondern eher von einem langsamen 
Abfall auszugehen. Wenn Du also einen Brown-Out-Detektor verwendest und 
bei dessen Aktivierung ein sd_raw_sync() vornimmst sowie sämtliche 
weiteren Schreibzugriffe unterbindest, sollte das genügen.

Gruß,
Roland

von Hannes (Gast)


Lesenswert?

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

Viele Grüße
Franz

von Pete K. (pete77)


Angehängte Dateien:

Lesenswert?

Ich raff es nicht, es wird keine SD-Karte mit beiliegender Schaltung und 
der neuen Library von Roland erkannt (Rückgabewert bei CMD_GO_IDLE_STATE 
ist 0x1FF).

- ATMega644P läuft mit 8 Mhz intern (sonst 20 Mhz)
- Compiliert mit Os und O1
- 47µF und 100nF direkt hinter dem Kartenslot
- ISP nicht angeschlossen
- LED gegen CS ist nicht bestückt
- Pullup an DO ist 165K (ist das zu groß?)
- WP und CD werden nicht genutzt
- sd_raw_available() fest auf return 1 gesetzt
- sd_raw_locked() fest auf return 0 gesetzt
- SD-Karte wird mit 3.29V (gemessen) versorgt
- Wartezeit bis sd_init ca. 3 Sekunden (I2C-Display wird initialisiert)

Ich habe 4 SD-Karten (16-64MB) probiert, alle funktionieren nicht. Auch 
ein Formatieren der Karten in einer Fotokamera hilft nicht.

Bin für jeden Tipp dankbar...

von Pete K. (pete77)


Lesenswert?

Habe gerade mal PB3-7 auf "on" gesetzt (PORTB |= (1<<PB3) etc.) und 
siehe da, an PB3 liegen 4,97V an, an PB4,5,7 nur 0,63V und an PB6 nur 
4,65V. Alles ohne Karte gemessen.

Merkwürdig...

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Pete!

Bist Du die FAQ auf meiner Homepage durchgegangen?

Ansonsten:
- Der MCP1700 könnte mit max. 250mA etwas zu schwach sein.
- An den Ein- und Ausgängen der Spannungsregler jeweils 100nF vorsehen.
- Wie lang sind die 3V3/MISO/MOSI/SS-Leitungen?
- Hast Du ein Oszilloskop, um diese Signale anzuschauen? Interessant
  wäre auch der 3V3-Verlauf während dem Anstecken der Karte.
- Verwendest Du ein ausreichend dimensioniertes Netzteil?
- 16MB-Karten sind mit FAT12 formatiert, die kannst Du mit meinem Code
  nur Raw ansprechen (ohne FAT).

Gruß,
Roland

von Roland R. (roland) Benutzerseite


Lesenswert?

Pete K. schrieb:
> an PB3 liegen 4,97V an

Ok.

> an PB4,5,7 nur 0,63V

Das ist schlecht.

> an PB6 nur 4,65V

Na gut, da treibt der 5V-Port-Pin über den Pullup nach 3.3V. Sollte bei 
165k gefühlsmäßig aber eigentlich auch höher liegen.

Hast Du Dein Layout/Aufbau kontrolliert? Anderen Controller ausprobiert?

Gruß,
Roland

von Pete K. (pete77)


Lesenswert?

Hallo Roland,

hier ein paar Antworten:

- Die Leitungen sind etwa 6cm lang.
- 3V3 Leitung ist kürzer
- Leider habe ich kein Oszi, ich kann nur per RS232 und Multimeter 
"debuggen"
- Das Netzteil schafft 600mA bei 7,8V laut Aufdruck
- Ich habe jeweils eine 16MB, 32MB und 64Mb SD-Karte sowie eine 16Mb 
MMC-Karte. Eine 8GB SDHC will ich da erst einmal noch nicht testen :-)
- Mit dem Multimeter kann ich beim Einstecken der Karte auf der 3V3 
Leitung keinen Spannungseinbruch erkennen. Ist aber wahrscheinlich auch 
zu träge dafür.

Anderen Controller, auch wenn das Flashen per ISP geht? Da werden ja 
auch keine anderen Pins benutzt...

Anbei das Layout, Massefläche habe ich ausgeblendet.

von Pete K. (pete77)


Angehängte Dateien:

Lesenswert?

Beim Bearbeiten kann man keine Datei anhängen.

von Roland R. (roland) Benutzerseite


Lesenswert?

A propos Pullup:
Ich weiß dass einige Leute hier empfehlen, einen solchen zu verwenden. 
Bisher habe ich diesen bei meinen Schaltungen aber nie verwendet.

Gruß,
Roland

von Pete K. (pete77)


Lesenswert?

Ein anderer Controller bringt die gleichen Ergebnisse.

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

von Pete K. (pete77)


Angehängte Dateien:

Lesenswert?

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

von Roland R. (roland) Benutzerseite


Lesenswert?

Pete K. schrieb:
> Ein anderer Controller bringt die gleichen Ergebnisse.
>
> Die CS-Leitung hat 1k8 Ohm gemessen vom µC Pin zum Slot. Stimmt soweit.

Hmm, bin da dann auch ein bisschen ratlos.

- Reset wirklich erst nach Abnehmen des ISP-Adapters losgelassen?
- Neues von Deinem Pegeltest? Pegelstände auf SD-Seite?
- sd_raw_config.h nochmal kontrolliert?
- Pullup an MISO mal weglassen?
- Liest der uC tatsächlich anliegende MISO-Werte? Test mit Draht ohne
  Karte? Ähnliche Experimente?

Gruß,
Roland

von Torsten S. (tse)


Lesenswert?

Weil auf Deiner Schaltung einige Peripherie zu sehen ist: läuft der 
sd-reader so wie er ist oder hast schon einige Sachen für Deine Hardware 
eingebaut?

von Pete K. (pete77)


Lesenswert?

Die Peripherie läuft, nur die SD-Karte nicht :-<

Ich habe jetzt die Pullups ausgelötet und nur die SD-Reader Sourcen 
benutzt. Leider klappt es immer noch nicht.

Parallel habe ich auf einem Steckbrett und einem SD-Kartenslot auf 
Lochraster auch mit Spannungsteiler getestet, dort kann ich eine 
SD-Karte erkennen (Disk-Info wird ausgegeben). Insofern ist die Software 
ok, da habe ich aber auch wirklich nicht dran gezweifelt :-)

Immerhin habe ich jetzt eine Karte, welche sicher funktioniert.

Aber irgendwo ist noch der Wurm drin....

von Torsten S. (tse)


Lesenswert?

Dann kann es doch nur noch an der Platine oder den Bauteilen liegen.

Ich hatte z.B. ein Problem mit den Anschlüssen an meinem Kartenhalter. 
Wenn man die weiter verfolgte sah alles sehr merkwürdig aus. Habs 
einfach durchgeklingelt.

von Pete K. (pete77)


Lesenswert?

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

Vielen Dank für eure Mithilfe!

von Torsten S. (tse)


Lesenswert?

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

von Pete K. (pete77)


Lesenswert?


von Torsten S. (tse)


Lesenswert?

Danke :)

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

Bei dieser Gelegenheit könntest Du auch viele unnötige pullups 
rauswerfen, z.B. um den Drehencoder und JP14..17. Schalte einfach die 
internen des AVR ein denn die Widerstandswerte sind nicht kritisch.

Damit gewinnst Du bestimmt Platz um die 3k3/1k8 Spannungsteiler als 
Pegelwandler für die SD-Karte durch etwas anständiges zu ersetzen. Z.B 
durch einen 74HC4050B den ich auch erfolgreich verwende. Kostet nur ein 
paar Cent.

von Dschadu (Gast)


Lesenswert?

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

von Kai J. (tairon)


Lesenswert?

Hallo

ich habe eine Frage zur maximal möglichen Anzahl an Dateien, die ich in 
einem Ordner auf der SD-Karte speichern kann.
Ich habe ein Testprogramm geschrieben, dass fortlaufend Dateien anlegt.
Bei einer 1GB Karte kann ich 255 Dateien in einem Ordner anlegen.
Bei einer 2GB Karte sind es 511 Dateien. Beide Karten mit FAT16 
formatiert (Panasonic SDFormater).

Danach habe ich die 1GB Karte mit FAT32 formatiert (Windows). Ich konnte 
dann nur 63 Dateien in einem Ordner speichern.

Weis jemand von was die maximale Dateianzahl abhängig ist, bzw. wie man 
die Anzahl erhöhen kann?

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Kai,

Kai J. schrieb:
> Weis jemand von was die maximale Dateianzahl abhängig ist, bzw. wie man
> die Anzahl erhöhen kann?

Generell ist die Anzahl der Dateien nur beim Wurzelverzeichnis von FAT16 
beschränkt, bei FAT32 bzw. bei Unterverzeichnissen allgemein gibt es 
keine Beschränkung.

Was passiert, wenn Du keine Dateien mehr anlegen kannst? Wie äußert sich 
der Fehler?

Gruß,
Roland

von Kai J. (tairon)


Lesenswert?

Hallo Roland,

das Programm bleibt dann einfach hängen.
Das passiert in der Funktion
1
fat_create_file(dd, filename, &file_entry)
wobei filename ein char-array ist, z.B. *254.txt*.

Ich habs jetzt noch mal genauer untersucht. Das Programm kommt aus der 
while(1) Schleife nicht mehr raus. Da drin läuft es bei mir ab der 
256-ten bzw. 512-ten Datei endlos weiter.

Gruß Kai

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Kai,

Ich habe Dein Problem eben lokal nachvollziehen können. Es ist ein Bug, 
der wohl leider schon länger besteht. Er tritt auf, wenn der letzte 
Eintrag eines Verzeichnisses direkt vor einer Clustergrenze liegt.

Werd mir mal Gedanken machen, wie man das beheben kann und mich dann in 
den nächsten Tagen zurückmelden.

Gruß,
Roland

von Roland R. (roland) Benutzerseite


Angehängte Dateien:

Lesenswert?

Hallo Kai,

Könntest Du bitte mal den angehängten Patch auf fat.c anwenden und mir 
von den Ergebnissen berichten? Bei mir tritt das Problem damit nicht 
mehr auf.

Gruß,
Roland

von Kai J. (tairon)


Lesenswert?

Hallo Roland,

jetzt klappt's wunderbar. Mein Programm ist bei 1000 Dateien ohne 
Probleme durchgelaufen. Ich probier mal aus, ob ich noch mehr Dateien 
anlegen kann.

Vielen Dank für die schnelle und freundliche Hilfe ;)

Gruß
Kai

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Kai,

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

Gruß,
Roland

von Hans (Gast)


Lesenswert?

Hallo Roland,

vielen Dank für Deine tolle Arbeit.
Meinst Du, man bekommt das auch auf einem xmega problemlos zum laufen?
Hast Du so was schon mal probiert?

Liebe Grüße, Hans

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Hans,

Zufällig habe ich vor kurzem einen Bericht erhalten, nachdem die 
Bibliothek auch auf dem XMega läuft. Wenn Du mir eine private Mail 
schreibst, antworte ich mit den Anpassungen, die mir zugeschickt wurden.

Gruß,
Roland

von Ivan H. (Gast)


Lesenswert?

Hallo zusammen!
zu meinem Problem: ich habe die neueste SD Library ausporbiert und in 
meinem Programm implementiert. Die Funktion sd_raw_init funktioniert, 
die Funktion sd_raw_get_info ebenfalls. rufe ich die Funktion 
sd_raw_read auf, kommt return 1 zurück -> soweit so gut. Ich habe den 
Offset 0 gewählt. Es werden aber keine Datenausgelesen, obwohl bei einem 
Offset = 0 der Beginn des Bootsektores des FAT Dateisystems zu sehen 
müsste...

Gruss,
Ivan

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Ivan,

Ohne ein paar genauere Angaben wird Dir hier keiner helfen können.
- Lese bitte die FAQ auf meiner Homepage.
- Welche MCU? Welches Board?
- Welche Daten werden zurückgeliefert?
- Funktioniert die sd-reader Anwendung (main.c) alleine?
- Relevanten Code posten?

Gruß,
Roland

von Hannes Ebner (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Leute,

ich habe ein problem ... mit der neuen version bekomme ich immer die 
meldung

> touch hannes.txt
error creating file: hannes.txt

wenn ich den alten code stand sd-reader_source_20090330  raufspiele 
gehts
sd-reader_source_20100110 bringt mit den fehler

hab den code zusätzlich angehängt falls ich wo n config fehler habe!

VIELEN DANK IN VORAUS

lg
hannes

von Hannes Ebner (Gast)


Lesenswert?

okay saublöder fehler ... irgendwo hats was mit dem writeprotect ... hab 
den bei der sd card reingegeben und nun gehts ... muss den pin negieren 
dann hauts auch mit dem nachbarn hin :-)

von hannes ebner (Gast)


Lesenswert?

hab aber ein problem mit der sd hc  ein file anlegen geht aber sobald 
ich den write befehl durchführe hängt er

> write hannes.txt 0
< es geht
error writing to file

danke für die hilfe in voraus

lg
hannes

von Ivan H. (Gast)


Lesenswert?

@Roland

Das Problem habe ich nun gelöst: es lag an der Speicherkarte, eine 1Gb 
Speicherkarte (Typ 2.0) kann ich problemlos beschreiben und wieder 
lesen. Ich lese Sektor 0 (erste 512 Bytes) aus und gebe sie über UARt an 
den PC aus. Mache ich das mit einer 2GB Karte (2.0), kommt irgendetwas 
daher, jedoch nicht der Bootsektor des FAT Dateisystems, mit einem 
HEX-Editor habe ich das überprüft. Die beiden Speicherkarten sind von 
SanDisk, die 1GB Karte ist ca. 2 Jahre alt, die 2GB Karte neu. Hat deine 
Library ein Problem mit 2GB Karten?

Gruess,
Ivan

von Roland R. (roland) Benutzerseite


Lesenswert?

@Hannes

Nachdem da bei Dir eine Fehlermeldung auftaucht, hängt er ja wohl nicht, 
sondern liefert nur eine Fehlermeldung zurück. Kannst Du nachvollziehen 
(mittels Debugger oder in den Code eingefügter printf()s), an welcher 
Stelle er mit dem Fehler aussteigt?

@Ivan

Normalerweise hat sd-reader kein Problem mit 2GB-Karten, ich verwende 
hier selbst eine. Womit ich jedoch keine Erfahrung habe, sind Karten mit 
weniger als 4GB (also nicht SDHC), die aber der Version 2 der 
SD-Spezifikation folgen.

Gruß,
Roland

von Hannes E. (hannes_ebner)


Lesenswert?

hallo roland,

werd ich machen, den fehler spuckt er nur aus wenn ich die sd hc karte 
rausgebe, irgendwas muss mit der sdhc sein weil er beim init sehr lange 
braucht. bei punkt free: "hängt" er n paar minuten und spuckt dann free: 
0/0 aus. ich hab nur einen typ sdhc karte transcend. vielleicht probier 
ich mal ne andere aus ... muss mir die erst kaufen.

sd funktioniert prima!!!

liebe grüße
hannes

von Roland R. (roland) Benutzerseite


Lesenswert?

Hallo Hannes,

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

Gruß,
Roland

von Hannes E. (hannes_ebner)


Lesenswert?

Hallo Roland,

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

Viele Grüße
Hannes

von Ivan H. (Gast)


Lesenswert?

Hallo Roland,

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

bei der Funktion sd_raw_read(0x00, ucBuffer, 512) kommt einfach nicht 
das heruas, was ich herauslese, wenn ich die Karte in den Reader stecke 
und mit dem HEX-Editor überprüfe.
Die Funktion UART_send_Block_while(ucBuffer, 512); sendet jeweils ein 
Array mit der Länge 512Bytes ans Terminal. Muss ich irgendwie zuerst 
eine Startadresse auslesen, wo das Dateisystem beginnt?
folgendes Kriege ich raus (Terminal):
...
0ðÀ vUª -> Das Uª (=55AA) ist interessant, da FAT "Checksumme"
SD read OK


Mit dem HEX-Editor lese ich auf Adresse 0 folgendes:
ëXMSDOS5.0

Wo liegt der Fehler?

gruss Ivan

von Werner B. (werner-b)


Lesenswert?

Der Sektor der 0x55AA endet ist der physikalisch erste Sektor der SD. Da 
steht die Partitionstabelle. An die kommst du unter Domesdos mit dem 
standard Debug.com nicht ran. (Ich kann mich erinnern dass man dafür den 
Symdebug = Debug.exe vom Macroassembler brauchte). Auch die Norton 
Utility ist da rangekommen. Was der Debug.com liefert ist der erste 
Sektor der DOS-Partion, aber nicht die Partitionstabelle bzw. der erste 
physikalische Sektor.

von Ivan H. (Gast)


Lesenswert?

@Werner B.
Danke für den Tipp, habe die umfangreiche FATFS von ElmChan mit der 
sd_raw.c von Roland verknüpft -> funktioniert wunderbar. Die Partition 
bzw. den MBR wertet die FATFS aus, der Rest ist kein Problem mehr.
Danke für eure Hilfe!

Gruss Ivan H.

von stuner (Gast)


Lesenswert?

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

von Julian W. (julian-w) Benutzerseite


Lesenswert?

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

von Martin J. (bluematrix) Benutzerseite


Lesenswert?

*abo

von Pete K. (pete77)


Lesenswert?

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

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

von Martin J. (bluematrix) Benutzerseite


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe 2 Probleme mit meiner SD Karte.

Hintergrund:
Für ein Projekt muss ich einen Datenlogger realisieren.
Geloggt werden GPS Daten und verschiedene Sensoren, welche über den CAN 
Bus empfangen werden.
Alle Daten ergeben maximal einen String von 300 Byte.
Dieser String soll mit einer festen Frequenz von 50Hz geloggt werden.
Prozessor ist ein AT90CAN128 mit 16MHZ.

Problem 1:
Leider habe ich aber schon bei 10 Hz Probleme mit der Reorganisation der 
Karte.
Momentan schreibe ich aller 100mSec einen String von 150 Byte mit 
folgendem Befehl auf die Karte.
1
if(fat_write_file(fd, (uint8_t*) sd_buffer, strlen(sd_buffer)) != strlen(sd_buffer))
2
{
3
uart1_puts("Fehler beim schreiben\n\r");
4
}                              
5
sd_raw_sync();

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

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

Schon mal vielen Dank
Martin
Martin Junghans

von Martin J. (bluematrix) Benutzerseite


Angehängte Dateien:

Lesenswert?

hier nochmal die main.c einzeln

von Meini (Gast)


Lesenswert?

Ich würd mal auf das Signal schauen das zu den SD Karten geht.
Keine Ahnung was du für ne Anpassung machst, oder ob du überhaupt eine 
hast.
Normalerweise läuft der MC auf 5v die Karte aber auf 3.3V.
Wenn du da einen Spannungsteiler (Widerstände) hast, ist das bei höheren 
Übertragungsfrequenzen fatal.
Wenn dem so ist nimm einen Level Shifter der macht das besser.

von Martin J. (bluematrix) Benutzerseite


Angehängte Dateien:

Lesenswert?

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

von Meini (Gast)


Lesenswert?

Schnell genug dürften die Linedriver ja sein, aber es sind keine 
Levelshifter.

Ich kann aus dem Schaltplan nicht erkennen mit welcher Spannung dein 
Prozessor arbeitet.
Aber wenn er mit 5 Volt arbeitet und der HTC125 mit 3,3Volt dann gibt 
das sicher Probleme.

Wenn dein Prozessor mit 3,3Volt arbeitet brauchst du aber nicht 
unbedingt den Linedriver, da die Ausgänge des Prozessor genügend Strom 
liefern um die SD Karte anzusteuern.

Dein Schaltbild lässt darauf schliessen, dass dein Prozessor über ein 
Kabel an die SDKarteneinheit angeschlossen ist.
Wenn das stimmt, wie lange ist das Kabel? geschirmt, ungeschirmt?
Mit welcher Taktfrequenz arbeitet der Bus?

von Meini (Gast)


Lesenswert?

Ach ja könnten sich die beiden SD Karten, die ja gemeinsam am Bus hängen 
gegenseitig beeinflussen?
Soweit ich erkennen kann gibt es nur ein CS für beide SD Slots.

von Martin J. (bluematrix) Benutzerseite


Lesenswert?

Prozessor arbeitet mit 5V
Das Flachbandkabel ist ungeschirmt und 8cm lang.
Es sind nicht mehrere Karten gleichzeitig am Bus.
Ich habe mir nur eine universal Platine gebaut, je nachdem welches SD 
Karten modul ich grad günstig zu kaufen bekomme.

Ich kann mir nicht vorstellen, dass es an der Kommunikation liegt.

Ich habe 3 Karten, bei allen funktioniert die Kommunikation "oft".

Ich habe mit Karte 1 zwei Tage lang problemlos bei vollem Speed 
getestet. Plötzlich geht es nicht mehr, ich kann nur noch die SD Karten 
Information auslesen, das Datenverzeichniss ausgeben, aber ich kann kein 
File mehr anlegen oder in kein File schreiben.
Nehme ich jetzt Karte 2 klappt alles wieder.

Wenn ich Karte 1 mit meinem Computer oder meinem Fotoapperat teste geht 
alles. Formatieren oder medium reparieren nützt nichts. Ich kann einfach 
nicht mehr auf die Karte schreiben.
Jedoch nach ein paar tagen pause geht die Karte wieder problemlos für 
die nächsten 40 Tests.

Woran kann das liegen, ich mache doch nichts besonderes in meinem 
Code!?!?!?

von Martin J. (bluematrix) Benutzerseite


Lesenswert?

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

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

von Meini (Gast)


Lesenswert?

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

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

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

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

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

von Martin J. (bluematrix) Benutzerseite


Lesenswert?

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

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

Danke martin

von Meini (Gast)


Lesenswert?

Hier mal ein Link zu einem Fertigen KartenModul mit Pegelanpassung.

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

von Martin J. (bluematrix) Benutzerseite


Angehängte Dateien:

Lesenswert?

könnt ihr mal über das Layout drüber schauen?

findet ihr Fehler?

einige machen an die Kommunikationsleitungen auf der Seite der SD Karte 
noch 3,3V pull up Widerstände, ander wieder nicht... was meint ihr?

Wie muss ich den Three-State Anschluss belegen?


Danke Martin

von Meini (Gast)


Lesenswert?

Ich hab so eine Pegelanpassung noch nie selbst aufgebaut, bzw benötigt.
Aber soweit ich erkennen kann sind bidirektionale Shifter so aufgebaut, 
dass sie nur wenig Strom am Ausgang liefern, und daher von einem µC 
Ausgang überschrieben werden können.
Das bedeutet aber auch, dass bei Batterieanwendungen ein erhöhter 
Stromverbrauch vorhanden ist.
Es gibt aber Level Shifter in dem ein und Ausgänge vorhanden sind, die 
halt nur als Ein bzw Ausgang verwendet werden können.

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