Also ich nutz seit einiger Zeit ne Compactflash als Festplatte.
Und habe noch keine Probleme gehabt.
Ich denke der Wert 100.000 ist der Garantierte Wert, die FLashs kommen
sicher noch höher.
Dank an Roland Riegel und die gesammte Open-Souce,
Mein Datenlogger funktionert endlich.
Was ich noch nicht verstehe ist, warum ich nach jedem ADC-Cannel wechsel
ne Dummymessung machen muß.
Hallo Michael,
Beim Formatieren sollte Windows für Karten <= 2GB meines Wissens nach
automatisch FAT16 verwenden. Rechtsklick auf Laufwerk und
"Formatieren..." wählen.
Ansonsten von einer Linux-CD booten und fdisk sowie mkdosfs verwenden.
Gruß,
Roland
Vielen Dank für Deine schnelle Antwort,Roland.
Ich werde es wohl mit Linux versuchen müssen, da ich mit Windows bisher
wenig, oder keinen Erfolg erzielen konnte.
Gruss,Michael
Hmm, warum willst Du die Karte eigentlich neu formatieren? Die werden
doch schon mit einem FAT16-Dateisystem ausgeliefert, welches einwandfrei
mit dem sd-reader funktionieren sollte.
Roland
Hallo Roland,
Du hast vollkommen Recht. Jedoch sind meine SD-Karten bereits schon mit
dem FAT 32 formatiert. Versuche jetzt deinen Vorschlag.
Viele Grüsse, Michael
hallo,
hat jemand ein ein schema fuer mich? moechte das
ganze mit nem atmega16 ausprobieren, da sind die
boardlayouts leider nicht sehr hilfreich.
mal das ganze dann schnell mit eagle um/nach und
stells hier rein.
danke
hansl
Hallo Guido,
Guido Fischer wrote:
> Glückwunsch zum Source - funktioniert!>
Danke!
> Ich hab mein Arthernet damit eben wiederbelebt da ich dort ja die MMC> fest drauf habe. Chip Select über das CPLD funktioniert leider nicht,> da das Programm nach Aktivierung des XMEM nicht mehr will.>
Meinen Respekt für Arthernet. Eine Menge Arbeit und sehr professionell.
Zu XMEM kann ich Dir nicht viel sagen, da ich es zwar schonmal benutzt
habe, die Schaltung jedoch keinen SD-Sockel hat. Was heißt, dass das
Programm nicht mehr will?
> Ich habe eine günstige 1GB Karte die auf Anhieb läuft und eine 512MB> Karte die sich nur durch zahlreiche Resets zur Antwort überreden lässt.> Ich versuch gerade herauszufinden, woran's liegt, komme aber nicht> weiter da mein JTAG streikt und das Arthernet Modul auch noch rumzickt.>
Wie wird denn die Versorgungsspannung für die Karte bereitgestellt? Ich
selbst habe die 3,3V mittels zweier Dioden erzeugt und hatte damit keine
Probleme. Andere berichteten damit jedoch teils von immensen Problemen,
da die Karten oft sehr hohe Spitzenströme von 100-200mA brauchen, bei
denen die Spannung einbricht. Ein eigener Spannungsregler wäre am
besten.
> Bei einer recht vollen Karte konnte ich keine Dateien mehr anlegen. Ich> hatte drei Ordner mit zig mp3 Files und im Root versucht eine Datei> anzulegen. Wurde ohne Fehler quittiert aber die Datei war nicht da.> Sobald ich das reproduzieren kann, schicke ich Dir dazu passende Infos.>
Ok, danke. Eventuell wäre auch ein Kartenimage sinnvoll.
> Jetzt guck ich erst mal, warum der JTAG nicht will :-/>> Gruß, Guido
Viele Grüße,
Roland
Servus Guido,
Guido Fischer wrote:
>> Wie wird denn die Versorgungsspannung für die Karte bereitgestellt?>> Separater 3.3V Spannungsregler und SPI über 74LVX125 entkoppelt.>
Ok, das sollte mehr als ausreichen. Vielleicht ist die Karte selbst
etwas zickig und man sollte die Anzahl der Initialisierungsversuche oder
die Wartezeiten innerhalb von sd_raw_init() nach oben setzen.
>> [Kartenimage]>> Bevor ich mir die Arbeit mache rauszufinden, wie ich das unter Windoof> hinkriege, schick ich Dir die 2,99 EUR Karte eher per Post ;-)>
Entweder so, oder mit dem Windows-Port von dd, siehe
http://www.chrysocome.net/dd
Falls Du es auf diesem Weg machen willst, könnte ich Dir ein bisschen
FTP-Platz bereitstellen.
> Btw. ich hab jetzt meinen RTC am rennen und wollte den Vorschlag> machen, neue Dateien optional mit einem Datum zu versehen. Ich hab zwar> schon mal versucht in den Structs die passenden Stelle zu finden, aber> das ist mir zu abstrakt - da kennst Du Dich besser aus.>
Bei mir im Code findest Du da nichts, weil ich das nicht vorgesehen
habe. Es sollte aber relativ einfach möglich sein, das zu
implementieren. Allerdings würde ich das wieder mit #defines
konfigurierbar machen, da solch ein Feature für die meisten Anwendungen
überflüssig sein dürfte.
Ich schau mir das bei Gelegenheit mal an. Allerdings würde ich darauf
verzichten, auch noch die Zeiten des letzten Zugriffs oder der letzten
Änderung aufzuzeichnen. Oder wüsstest Du eine vernünftige Anwendung
dafür?
Grüße,
Roland
Hallo Guido,
Hmm, das ist merkwürdig. Ich habe hier ein mega128 ENC28J60-Board
liegen, welches SPI und XMEM verwendet. Wenn Du magst, kann ich Dir ja
mal ein abgespecktes Grundgerüst von meinem Code schicken.
Mittlerweile habe ich den sd-reader FAT16-Code so erweitert, dass das
Erstellungsdatum und die -zeit gelesen und gesetzt werden kann.
Durchgetestet habe ich das aber noch nicht.
Viele Grüße,
Roland
Auf die Erweiterung mit Datum/Uhrzeit bin ich auch gespannt...
Bei mir ist es so das der sd-reader in meinem eigenen Projekt seit
geraumer Zeit erfolgreich läuft. Allerdings in einer älteren Version;
das Problem mit Verzeichnissen unter m$ kann ich nachvollziehen wie hier
gepostet wurde.
Nun habe ich etwas Angst alle Dateien mit denen von einer neueren
Version mit einem Schlag einfach zu ersetzten. Möglicherweise sind
eigene 'Anpassungen' drin die ich einfach vergessen habe.
Roland, könntest Du evtl. ein Diff zwischen den einzelnen Versionen mit
veröffentlichen? Das wäre sehr hilfreich.
Danke noch einmal für alles,
Torsten
@Guido,
Naja, ob das gleich Genialität beweist ;-)
@Torsten,
Bei Gelegenheit (sprich: dem nächsten Release) werde ich das machen. Bis
dahin kannst Du Dir auch selbst behelfen:
diff -ur [sd-reader_verzeichnis] [verzeichnis_mit_deinem_code] >
deine_aenderungen.patch
Oder z.B. auch:
diff -ur sd-reader_source_20061101 sd-reader_source_20070301 >
sd-reader_diff_20061101_20070301.patch
Zurückspielen tust Du das dann in dem Verzeichnis, wo der zu patchende
Code liegt:
patch -p1 -i deine_aenderungen.patch
Du kannst obiges auch noch um --dry-run ergänzen, um zunächst nur mal zu
sehen, ob es Konflikte geben wird.
Bei diesen Experimenten solltest Du vorher natürlich Backups machen...
Grüße,
Roland
Hallo zusammen,
@Guido: Die Probleme sind mir seinerzeit bei der Anpassung von Rolands
SD Library nicht aufgefallen.
Ich benutze auch dein Arthernet zusammen mit Rolands Library und einer
32MByte NoName MMC Karte und einer 128MByte NoName SD Karte.
Die gehen beide problemlos. Ok, ich lese von der Karte.
Der entscheidende Teil der sd_raw_config.h sieht bei mir so aus:
1
#elif defined(__AVR_ATmega64__) || \
2
defined(__AVR_ATmega128__)
3
/* Attention: all pins must be defined for correct work */
4
#define configure_pin_mosi() DDRB |= (1 << PB2)
5
#define configure_pin_sck() DDRB |= (1 << PB1)
6
#define configure_pin_ss() DDRB |= (1 << PB0)
7
#define configure_pin_miso() DDRB &= ~(1 << PB3)
8
9
#define select_card() *pSPI_CS &= ~(1 << SPIP4)
10
#define unselect_card() *pSPI_CS |= (1 << SPIP4)
11
#else
Zu JTAG kann ich leider nichts sagen ich benutze nur den ISP Anschluss.
Tschau
Michael
@Guido, Torsten und andere Interessierte,
Angehängt findet Ihr nun einen Patch, der das Erstellungsdatum von
Dateien und Ordnern setzt. Er sollte funktionieren, allerdings konnte
ich ihn nicht richtig testen, da
1. an meinem sd-reader keine RTC vorhanden ist und
2. mein kleiner mega168 durch die 5Byte größere fat16_dir_entry_struct
mal wieder Platzprobleme im Stack bekommt.
Vielleicht könntet Ihr die Änderungen mal antesten. Bitte ändert in
fat16_config.h das define fat16_get_datetime ab, sonst wird immer der
01.01.2007 eingetragen.
Viele Grüße,
Roland
Oder guck einfach mal per Wordpad in die .patch-Datei. Das Format ist
eigentlich selbsterklärend. Zur Not kannst Du es also per Hand mergen.
Bin schon gespannt auf Eure Ergebnisse...
Gruß,
Roland
Roland,
Offen gestanden hat es mich erhebliche Überwindung gekostet um den neuen
Code auszuprobieren. Sachen die gut laufen sollte man eigentlich nicht
mehr anfassen. ;)
Zuerst habe ich ein Update auf 20070301 gemacht. Per Hand so wie Guido,
mit copy&paste nach dem diff zu der alten Version. 'patch' traue ich
mich nicht auf meine Sourcen loszulassen.
Dabei ist mir aufgefallen, daß Du die GPL entfernt hast. Was bedeutet
das jetzt genau?
Dann den neuen patch per Hand eingebaut. Aus Bequemlichkeit und/oder
Vorsicht belasse ich erst einmal die Zeit so wie sie ist mit dem
eingebauten #define fat16_get_datetime. Die Daten sind mir wichtig, ich
möchte nichts riskieren. Das Datei-Datum jetzt vom RTC zu holen bedeutet
einiges an meinem Proggi umzubauen.
Ich habe dann einige neue Dateien mit dem AVR erzeugt. Anschließend die
Karte in XP's Card-Reader eingesteckt. Kein Datum im Explorer. :(
Cmd in XP ausprobiert: Ein 'dir' zeigt für eine Datei z.B.
01.01.1601 02:00 166.828 01.txt
Bestimmt habe ich irgendwo einen typo. Nur wo?
Kann ich evtl. an einer sinnvollen Stelle ein paar Bytes zur V24
schicken zum gucken was los ist? Oder muß ich die Karte neu formatieren
(was ich eigentlich nicht glaube)?
Hmm, bin etwas ratlos.
Torsten
Hallo Torsten,
T.S. wrote:
> Roland,>> Offen gestanden hat es mich erhebliche Überwindung gekostet um den> neuen Code auszuprobieren. Sachen die gut laufen sollte man eigentlich> nicht mehr anfassen. ;)>
Nun, gegen diese Ängste gibt es Versionskontrollsysteme oder, in der
simpelsten Form, Backups :)
> Zuerst habe ich ein Update auf 20070301 gemacht. Per Hand so wie Guido,> mit copy&paste nach dem diff zu der alten Version. 'patch' traue ich> mich nicht auf meine Sourcen loszulassen.>
Naja, ich denke die Wahrscheinlichkeit, dass Du per Hand einen Fehler
machst, ist größer als die Wahrscheinlichkeit, dass "patch" etwas falsch
abändert und keine Konflikte meldet.
> Dabei ist mir aufgefallen, daß Du die GPL entfernt hast. Was bedeutet> das jetzt genau?>
Was meinst Du mit "die GPL entfernt"? Welche Version hattest Du vorher
genau?
Der Code ist und bleibt unter der GPL. Soweit ich mich erinnere, habe
ich vor einigen Versionen lediglich mein Copyright und einen Vorspann zu
jeder Datei hinzugefügt.
> Ich habe dann einige neue Dateien mit dem AVR erzeugt. Anschließend die> Karte in XP's Card-Reader eingesteckt. Kein Datum im Explorer. :(>> Cmd in XP ausprobiert: Ein 'dir' zeigt für eine Datei z.B.>> 01.01.1601 02:00 166.828 01.txt>
1601? Das kann FAT eigentlich gar nicht darstellen. Kontrolliere
vielleicht nochmal nach, ob Du die Funktionen
fat16_set_file_creation_date() und fat16_set_file_creation_time()
korrekt übernommen hast.
> Bestimmt habe ich irgendwo einen typo. Nur wo?> Kann ich evtl. an einer sinnvollen Stelle ein paar Bytes zur V24> schicken zum gucken was los ist? Oder muß ich die Karte neu formatieren> (was ich eigentlich nicht glaube)?>
Du könntest innerhalb von fat16_create_file() nach dem Aufruf der beiden
oben genannten Funktionen den Inhalt der Variablen
dir_entry->creation_date und dir_entry->creation_time ausgeben lassen.
Wenn Du noch eine alte Version Deines Codes hast, könntest Du auch mal
einen Patch gegen Deinen jetzigen Code erstellen und diesen mit meinem
geposteten Patch vergleichen.
> Hmm, bin etwas ratlos.>
Das wird schon ;-)
Gruß,
Roland
Hallo Roland,
> Was meinst Du mit "die GPL entfernt"? Welche Version hattest Du vorher> genau?
Eine ältere Version, welche genau habe ich vergessen.
Da habe ich etwas falsch verstanden. Bitte entschuldige.
Btw wenn Du CVS verwendest, könnte man $Id$ einfügen, das zeigt die
letzte Änderung an.
Um Tippfehler auszuschließen habe ich jetzt auf die Version 20070301
patch losgelassen:
patch -i sd-reader_fat16-time.patch.txt
Die 3 betroffenen Dateien habe ich in mein Projekt kopiert. Zusätzlich
noch etwas debug-code in fat16_create_file und fat16_create_dir
spendiert:
...
fat16_get_datetime(year, month, day, hour, min, sec);
fat16_set_file_creation_date(dir_entry, year, month, day);
fat16_set_file_creation_time(dir_entry, hour, min, sec);
printf_P((PSTR("%02d.%02d.%04d %02d:%02d:%02d\r\n")),
day, month, year, hour, min, sec);
...
Auf der Konsole so wie es sein sollte:
01.01.2007 00:00:00
beim erzeugen von Dateien oder Verzeichnissen. Also arbeitet die
Funktion soweit.
Trotzdem das gleiche wie gestern beschrieben.
Vielleicht geht's mit einer anderen Karte, mal sehen.
Torsten
Hi Torsten,
> Btw wenn Du CVS verwendest, könnte man $Id$ einfügen, das zeigt die> letzte Änderung an.>
Ich verwende Subversion, aber da geht das auch, ja.
> Um Tippfehler auszuschließen habe ich jetzt auf die Version 20070301> patch losgelassen:> patch -i sd-reader_fat16-time.patch.txt>> Die 3 betroffenen Dateien habe ich in mein Projekt kopiert. Zusätzlich> noch etwas debug-code in fat16_create_file und fat16_create_dir> spendiert:>
Das heißt, im Prinzip verwendest Du jetzt meinen Original-Code? Schön.
> ...> fat16_get_datetime(year, month, day, hour, min, sec);> fat16_set_file_creation_date(dir_entry, year, month, day);> fat16_set_file_creation_time(dir_entry, hour, min, sec);>> printf_P((PSTR("%02d.%02d.%04d %02d:%02d:%02d\r\n")),> day, month, year, hour, min, sec);> ...>> Auf der Konsole so wie es sein sollte:> 01.01.2007 00:00:00> beim erzeugen von Dateien oder Verzeichnissen. Also arbeitet die> Funktion soweit.
Alles was das aussagt ist, dass fat16_get_datetime() funktioniert, und
das sind ja im Moment nur einfache Zuweisungen. Ich wollte explizit den
Wert von dir_entry->creation_date/time wissen. Der sollte 0x3621 (für
01.01.2007) bzw. 0x0000 (für 00:00:00 Uhr) sein. Nur die Werte innerhalb
von dir_entry werden dann auch von fat16_write_dir_entry() auf die Karte
geschrieben.
> Trotzdem das gleiche wie gestern beschrieben.> Vielleicht geht's mit einer anderen Karte, mal sehen.>
Ich glaube nicht, dass das an der Karte liegt. Das hat nichts mit der
physikalischen Ebene zu tun.
Grüße,
Roland
Hallo Roland,
> Das heißt, im Prinzip verwendest Du jetzt meinen Original-Code? Schön.
Yep.
> Alles was das aussagt ist, dass fat16_get_datetime() funktioniert, und> das sind ja im Moment nur einfache Zuweisungen. Ich wollte explizit den> Wert von dir_entry->creation_date/time wissen. Der sollte 0x3621 (für> 01.01.2007) bzw. 0x0000 (für 00:00:00 Uhr) sein. Nur die Werte innerhalb> von dir_entry werden dann auch von fat16_write_dir_entry() auf die Karte> geschrieben.
Achso. Schon wieder habe ich etwas falsch verstanden, ich bitte abermals
um Entschuldigung.
Die beiden printf_P's habe ich nun geändert, sind noch an der gleichen
Stelle:
printf_P((PSTR("date: 0x%04x time: 0x%04x\r\n")),
dir_entry->creation_date, dir_entry->creation_time);
Ich hoffe das war richtig. Heraus kommt:
date: 0x3621 time: 0x0000
> Ich glaube nicht, dass das an der Karte liegt. Das hat nichts mit der> physikalischen Ebene zu tun.
Wie Du richtig vermutet hast hat sich mit einer anderen Karte nichts
geändert.
Debuging ist keine einfache Sache und kann evtl. länger dauern weil
alles mögliche dafür in Frage kommen kann. Wir könnten versuchen der
Sache auf den Grund zu gehen wie schon einmal per PM wenn Du möchtest.
Es schreibt sich halt einfach leichter.
Torsten
Hallo zusammen,
da hier alle SD-Karten Kompetenzen versammelt sind trau ich mich mal
eine frage zu stellen.
Ich bestreite gerade ein Projekt indem ich eine SD-Karte mit Fat16
formatierung an ein Tricore 1130 µC anbinden soll.
Im wesentlichen hab ich die Sourcecodes von Ulrich Radig übernommen,
will sagen ich hab sie an meinen µC angepasst.
Da mein µC auf 3,3V läuft hab ich die SD-Karte quasi Eins zu Eins an den
Port geklemmt.
Ich habe jetzt allerdings ein problem bei der Initialisierung der Karte.
Nachdem ich die mind. 74 Clocks an die SD-Karte bei CS=High schick,
sende ich ja das CMD 0 bei CS=LOW. Sämtliche Übertragungen der Bytes hab
ich mit dem Oszi überprüft. Nach Plan sollte die Karte dann ja 0x01hex
zurücksenden.
Die Antwort die ich bekom ist allerdings 0x3fhex.
Meine Frage lautet nun: Wie kann die SD-Karte mir z.b. einen Illigal
Command Error zurücksenden, obwohl ich doch 6 Bytes für Commando 0
hinschick.
Ich komm einfach nicht dahinter was mir die Karte damit sagen will.
Meinen Quellcode habe ich mal angehängt.
Für eine erleuchtende Antwort wäre ich euch dankbar.
Mir fällt etwas auf in
while(sd_write_command(cmd)!=0x01)
{
if(Timeout++ >= 10) <--- [*]
{
return (1);
}
}
[*] Das Timeout ist auf jeden Fall zu kurz. Ich glaube irgendwo mal
gelesen zu haben das das Aufwecken der Karte fast eine Sekunde dauern
kann.
Torsten
Hallo!
Frage nebenher: Hat hier schonmal jemand den Datendurchsatz für einen
SCHREIBvorgang getestet?
Ich übertrage mit 38.400 baud (8N1) über uart eine binäre Datei. Das
macht max. 3.840 Nutzbytes/s. Ohne auf die SD-Karte zu schreiben (im
Quelltext, wenn MACHS_WIRKLICH nicht definiert ist) erreiche ich dieses
Maximum auch tatsächlich fast. Bin ich maximal 1s drüber bei einer 64kB
Datei.
Wenn ich nun aber auf die Karte schreibe sinkt die Übertragungsrate auf
aller höchstens 120 Byte/s. Wohlgemerkt Byte - keine kB! Eine 20kB
Firmwaredatei braucht plötzlich über 3 Minuten. Dabei habe ich den
Schreibpuffer (s. Quelltext) auf satte 512 Byte eingestellt.
Habt ihr das Problem auch oder ist das normal, weil FAT aufwendig ist?
Grüße!
Mathias
Schau Dir doch bitte einmal die Datei sd_raw.c vom sd-reader genauer an
weil es sich in diesem Thread genau darum dreht ;)
Ob ein Timeout von 1000 für eine Zeit von rund ~1s reicht wage ich stark
zu bezweifeln. Das geht nur bei den AVR's weil man jeden Takt zählen
kann und somit die Ausführungszeit vorhersagbar ist.
Nur Vermutungen weil ich von dieser CPU/MPU noch nie etwas gehört habe:
- der Code wird in einem Cache ausgeführt
- der Compiler optimiert stark
... so das Deine Schleifen in einem 'Wimpernschlag' ausgeführt werden
nicht aber in der Größenordnung die benötigt wird.
Möglicherweise hat der Tricore einen Timer. Wenn ja, verwende besser
diesen für einen Timeout.
Torsten
Hallo Roland,
ich habe deine Schaltung nachgebaut, allerdings mit Mega64 und meine
Kontrolle ober Karte gesteckt bzw schreibschutz liegen immer auf low, da
ich keinen Sockel habe.
Problem ist aber, dass sich die Karte nicht (richtig) initialisieren
lässt.
wenn ich die Karte n paar mal rausnehme und wieder reinstecke gehts mit
viel glück.
Habe das Problem verfolgt und hab dann herrausgefunden dass er mir in
der Funktion sd_raw_init da aussteigt:
/* reset card */
uint8_t response;
for(uint16_t i = 0; ; ++i)
{
response = sd_raw_send_command_r1(CMD_GO_IDLE_STATE, 0);
if(response == (1 << R1_IDLE_STATE))
break;
if(i == 0x1ff)
{
unselect_card();
return 0;
}
}
woran könnte das liegen? hab schon verschiedene Karten ausprobiert und
bei allen das selbe Syndrom.
Danke Stefan
Hallo Stefan,
stefan richter wrote:
> [...] da ich keinen Sockel habe.>
Was verwendest Du denn dann??
> Problem ist aber, dass sich die Karte nicht (richtig) initialisieren> lässt.
- Welche Anbindung?
- Stromversorgung per Wandler oder mit Dioden?
- Extra Pegelwandler oder Spannungsteiler?
Vor allem die letzten zwei Punkte sind kritisch. Wenn dann noch lange
Kabel oder Selbstbau-Sockel dazukommen, kann es durchaus Probleme geben.
Siehe dazu auch die Beiträge weiter oben im Thread.
Gruß,
Roland
Hallo Stefan,
Habe auch mal das Filesystem von Roland auf einem Mega64 probiert.
Am Anfang hatte ich auch Probleme.
Eines davon war bei sd_raw_init:
/* card needs 74 cycles minimum to start up */
for(uint8_t i = 0; i < 10; ++i)
Bei mir wurden komischerweise nur 5 Datenpakete ausgegeben (gemessen).
Weiss der Geier, warum..
Nachdem ich es geändert hatte in
/* card needs 74 cycles minimum to start up */
for(uint8_t i = 0; i < 20; ++i)
lief es einwandfrei.
Es ist ja ein Minimumwert. Mehr 0xFF-Bytes zu senden, schadet nichts.
Wichtig ist auch, dass der SPI Takt bei Init nicht über 400KHz liegt.
Und selbstverständlich, dass der Chip-Select für die Karte richtig
angesteuert wird.
Roland:
Welchen maximalen Lesedurchsatz hast Du hinbekommen?
Ich habe nur max. 250KBytes/Sek. geschafft. Für 512 Bytes, was einem
Sektor entsprechen sollte:
/* load file contents for speed measurements */
uint8_t buffer[512];
while(fat16_read_file(fd, buffer, sizeof(buffer)) > 0)
{
}
Ich verwende keine SPI, sondern ein externes CPLD, welches eine SPI mit
25MBits/Sek. enthält. Der Datenaustausch erfolgt rein über
Speicherzugriffe und der Status der SPI wird über einen Portpin
abgefragt, z.B. Senden:
void sd_raw_send_byte(uint8_t b)
{
uint8_t *SDAddress;
uint16_t i;
if (Initcard == 1)
i = 0x1101; //write INIT Mode 400KBits/Sek.
else i = 0x1102; //write fast mode 25MBits/Sek.
SDAddress = (uint8_t *) i;
*SDAddress = b; //write Data
_asm__ __volatile_ ("nop"); //allow "Ready" to change
while (PIND & (1<<PIND0)) //wait for "Ready"
{
}
}
Dein Filesystem ist sehr komfortabel. Bin zwar noch nicht ganz
durchgestiegen, weil ich noch nicht solange in C programmiere, aber es
funzt. Was ich noch gerne machen würde, wäre den Zeichenvergleich für
den Dateinamenszugriff Case-unabhängig zu machen. So dass man beim
Konsolenbetrieb nicht immer exakt auf Groß/Kleinschreibung achten muss.
Bin aber noch nicht durch Deine Strukturen durchgestiegen, bzw. wie die
Eingabestrings mit den Dateinamen verglichen werden.
Auch will ich mal versuchen, komplette Sekoren oder gar Cluster komplett
einzulesen, ohne die ständigen Bereichsabfragen, die (so wie es
aussieht), das ganze ziemlich ausbremsen.
Aber sonst: Hohes Lob!
Joachim
Joachim wrote:
> Roland:> Welchen maximalen Lesedurchsatz hast Du hinbekommen?> Ich habe nur max. 250KBytes/Sek. geschafft. Für 512 Bytes, was einem> Sektor entsprechen sollte:> [...]
Mit diesem Wert bist Du recht gut dran. Konkrete Messungen habe ich bei
mir allerdings noch nicht gemacht. Mein SPI läuft mit 8MHz, schon daher
dürfte der Durchsatz um ein Vielfaches geringer sein.
Generell gilt, je größer die Blöcke sind, die Du auf einen Schlag liest,
desto geringer ist der Overhead und desto schneller somit der Durchsatz.
Versuch es, je nach RAM-Ausstattung Deines Controllers, also mal mit
Blöcken von 1kB, 2kB oder mehr.
> Was ich noch gerne machen würde, wäre den Zeichenvergleich für> den Dateinamenszugriff Case-unabhängig zu machen. So dass man beim> Konsolenbetrieb nicht immer exakt auf Groß/Kleinschreibung achten muss.> Bin aber noch nicht durch Deine Strukturen durchgestiegen, bzw. wie die> Eingabestrings mit den Dateinamen verglichen werden.
Dazu ist es nicht unbedingt nötig, meinen Code zu ändern. Das kannst Du
auf Applikationsebene machen, wenn Du alle Dateien entweder in Groß-
oder in Kleinschreibung abspeicherst und alle Strings, die meinem
FAT16-Layer übergeben werden, zuvor entsprechend in Groß- oder
Kleinschreibung konvertierst.
Das hätte auch den Vorteil, dass Du meinen Code leichter auf neuere
Versionen aktualisieren kannst.
> Auch will ich mal versuchen, komplette Sekoren oder gar Cluster> komplett einzulesen, ohne die ständigen Bereichsabfragen, die (so wie> es aussieht), das ganze ziemlich ausbremsen.
Welche Abfragen genau? Die Dateien müssen in Cluster aufgeteilt werden,
da diese über den Datenträger verstreut liegen können. Die Aufteilung in
Sektoren (bzw. Blöcke) ergibt sich durch die Struktur der SD-Karten.
Eine Beschleunigung kann man z.B. durch
- Vergrößerung des Blockpuffers,
- Zwischenpufferung der Verzeichniseinträge und
- Zwischenpufferung der FAT
erreichen. Das habe ich aber zwecks guter Einsetzbarkeit auf möglichst
vielen verschiedenen Controllern und mangels RAM auf meinem mega168
nicht implementiert.
Gruß,
Roland
hallöle,
funzt der code auch mit sehr grossen speicherkarten (ca. 10 GB oder so)?
sorry, aber ich wollt' mir nicht alle ~300 beiträge hier durchlesen...
Hallo Peter,
FAT16 unterstützt nur Partitionsgrößen bis 2GB, dies gilt daher auch für
meinen Code. Unterstützt werden Medien bis 4GB, welche mit mindestens 2
Partitionen nutzbar sind.
Gruß,
Roland
Hallo an alle,
Nachdem ich von Torsten eine positive Rückmeldung für die Unterstützung
der Modifikationszeit bekommen habe, hier ein neues Release.
Die Änderungen im einzelnen:
- Unterstützung für das Lesen und Setzen der Modifikationszeit neu
angelegter oder geänderter Dateien und Ordner.
- Bugfix für einen Fehler in sd_raw_read() bei Benutzung des
Blockpuffers.
Ab sofort stehen auf meiner Homepage auch Patches bereit, die nur die
Änderungen seit des jeweils letzten Release enthalten. Diese sollten ein
Update erleichtern, insbesondere wenn in der Zwischenzeit eigene
Änderungen vorgenommen wurden.
Viele Grüße,
Roland
Hallo!
Hatte oben mal geschrieben, dass der Schreibdurchsatz sehr gering sei.
Das wollte ich hiermit mal klar stellen ging auf meine Kappe. Hatte
schon vor ein paar Wochen rausgefunden, dass ich den sizeof falsch
verwendet habe und eine Puffergröße von 2 Bytes statt 512 hatte. Aber da
sieht man mal, wie entscheidend diese Puffergröße ist.
Vielen Dank für die Aufnahme meines Patches. Ist ja doch noch eine Menge
Leben drin in den Routinen.
Grüße!
Hallo,
ich suche die Original-CID und -CSD der SD-Karten
Kingston Elite Pro 256MB
Platinum 1GB
Fragt mich nicht wie, aber mir ist es (unfreiwillig) gelungen,
die read-only-Register CID und CSD dieser Karten kaputt zu bekommen.
Bei der Kingston-Karte steckt eine halbe Kopie der CSD in dem CID-
Register.
Bei der Platinum-Karte stimmt die CRC7 bei CSD nicht. Was wieder
eine ganze Reihe von Fragen aufwirft. ;-)
Vielen Dank!
August
Hallo Roland,
ich brauche für ein GPS-Fahrtenbuch Schreibzugriff auf eine MMC, also
habe ich dein Projekt getestet:
-Mega16 auf das STK500 gesteckt
-Vtarget auf 3.3V konfiguriert
-MMC Sockel mit einem Stück Flachbandkabel an PORTB angesteckt
-Projekt kompiliert & geflasht
-> Funktionierte auf Anhieb wunderbar!
Wenn meine Platine da ist werde ich dann noch das NMEA Parsen & GPX
schreiben (das Gerät soll direkt GPX Dateien auf die Karte schreiben)
implementieren. Ich habe auf der Platine einen Goldcap mit 470.000 µF
vorgesehen, mal sehen ob das reicht um die Daten noch gar auf die Karte
zu schreiben wenn der Strom abgestellt wird...
Also vielen Dank für das Projekt,
Gruß
Stefan
Hi,
hab folgendes problem mit dem Code
sd_raw_init()
partition_open()
fat16_open()
fat16_get_dir_entry_of_path()
und fat16_open_dir()
sind erfolgreich. Wenn ich dann aber fat16_create_file() oder
fat16_create_dir() benutzen will, hängt er sich auf oder hat den Fehler,
dass er keinen freien Clsuter findet.
Die MMC wurde mit knoppix auf fat16 partitioniert (16 MB groß) und mit
mkdosfs formatiert.
Bin echt am verzweifeln, weil ich keinen logischen Grund finde...
Grüße
Christian
hallo,
ich hab grad laut anleitung von ulrich radigs webseite ein
brotbrett bestueckt.
http://www.ulrichradig.de/site/atmel/avr_mmcsd/gfx/MMCSDSCH.JPG
der aufbau ist:
ein stk500 mit atmega16 und 16MhZ quarz (laeuft).
die +5V beziehe ich vom VTG anschluss an portB.
sollten da beim mmc anschluss nach den 2 dioden nicht um die 3.7V
zu messen sein? bei mir ist es davor: 4.96V und nach den 2 1N418 4.32V.
jemand ne idee wo ich mich verbastelt haben koennte?
mfg
Hansl
@ jemand
Genau. Die nächste Frage von Hansl kann man schon raten.
Wieso funktioniert SPI mit den Spannungsteilern
nicht bei 8MHz ;)
Es ist doch immer wieder das gleiche leidige Thema :(
holger:
pack deine kristallkugel wieder ein und entspann dich.
mcu ist geflasht. ausgabe am terminal is auch da.
nun brauch ich nur noch irgendwo die mmckarte fat16 formatieren.
mfg
hansl
SPI funktioniert bei mir sehr wohl mit den Spannungsteilern, auch bei
14,x MHz. Die 3,3V Spannungsversorgung mit der Diodenlösung dagegen
nicht. Unbedingt, das wurde mehrfach erwähnt, einen eigenen Regler dafür
verwenden.
VORSICHT mit dem LM317 und einigen 3,3V Festspannungsreglern: Manche
brauchen eine Mindestlast von einigen mA!
Eine SD-Karte braucht nur Strom wenn darauf zugegriffen wird. Bei einem
ungeeigneten Regler könnte die Spannung auf unzulässige Werte
hochlaufen.
Sehr gute Erfahrungen habe ich mit einem "LP 2950 CZ-3,3" gemacht.
Meinen 5V-Regler (78L05) habe ich wegen der guten Erfahrungen durch
einen "LP 2950 CZ-5,0" aus der gleichen Familie ersetzt. Ein feines Teil
btw, der Ruhestrom liegt im µA Bereich. Das kann wichtig für
Batterie-Betrieb sein: der Ruhestrom ist ca. 5mA geringer pro Regler.
Beide gibt es für 60 Cent bei Segor.
Torsten
Hallo,
torsten: danke, hab diese fehlerquelle mal enfernt.
Hab nun anstelle der moeglicherweise wackeligen diodenloesung genau
wie stefan ein paar posts weiter oben beschrieben hat die VTARGET
konfigurationsmoeglichkeit des stk500 benutzt.
Leider ist alles was in der console zu sehen ist dies hier:
"MMC/SD initialization failed"
jemand ne idee woranns liegen koennte? oder kommt die meldung
auch wenn kein-oder ein ungueltiger partitiontable oder fat
gefunden wurde?
hier noch ein paar details zum setup:
SPI ist enabled (0)
die konfiguration der Anschluesse beim Atmega16:
PORTB4(SS) - MMC CS *via spannungsteiler
PORTB5(MOSI) - MMC DI *via spannungsteiler
PORTB6(MISO) - MMC DO
PORTB7(SCK) - MMC CLK *via spannungsteiler
uisp -dprog=stk500 -dserial=/dev/ttyS0 -dspeed=115200 -dpart=atmega16
--rd_aref --rd_vtg --rd_fuses
Firmware Version: 1.14
VTarget = 3.3 V
ARef = 3.3 V
Atmel AVR ATmega16 is found.
Firmware Version: 1.14
Fuse Low Byte = 0xff
Fuse High Byte = 0xd9
Cannot read extended fuse bits on this device. Returning 0xff
Fuse Extended Byte = 0xff
Calibration Byte = 0xbf -- Read Only
Lock Bits = 0xff
BLB12 -> 1
BLB11 -> 1
BLB02 -> 1
BLB01 -> 1
LB2 -> 1
LB1 -> 1
achja, die karte ist ne 128MB MMC - takeMS. die hab ich noch
nie benutzt, weis also weder ob noch wenn womit die formatiert ist.
mfg
hansl
> jemand ne idee woranns liegen koennte? oder kommt die meldung> auch wenn kein-oder ein ungueltiger partitiontable oder fat> gefunden wurde?
Ähem - wenn Du die Sourcen durchlesen würdest, wüsstest Du, dass bei
DIESER Meldung noch gar kein Partitionseintrag eingelesen wurde.
Diese Meldung bezieht sich rein auf sd_raw_init().
Die Karte sendet also keine gültigen Response-Daten.
Also zu 90% Hardware- oder Interface-Fehler.
Musst halt mal anzeigen lassen, was die Karte überhaupt antwortet. Wenn
sie denn überhaupt antwortet.
NEUE Karten in der Größe <=2GB sollten ab Werk ausschließlich mit FAT16
formatiert sein. Ich habe noch niemals eine andere gesehen und schon ca.
300 Stück verschiedener Karten "verbaut".
Vorsicht bei gebrauchten aus Ebay: Da wurde oft schon drauf
rumgepfuscht.
Wenn die Karte unter Windows neu formatiert wird, macht Windows in
vielen Fällen FAT12 draus, wenn die Karte relativ klein ist (z.B. 64MB).
Bei ersten Versuchen würde ich Billigkarten vermeiden.
Manche haben ein Problem mit dem SPI-Modus, obwohl sie in Kameras oder
Cardreadern problemlos laufen. Will hier keine Schleichwerbung machen,
aber Karten von SanDisk oder Kingston waren bei mir immer problemlos.
Zum Thema "Spannungsteiler mit Widerständen" wollte ich noch sagen, dass
die allseits bekannte Schaltung bis 4MHz funktioniert. Bei meinem M16C
Kontroller geht das sogar noch bei 8MHz SPI-Takt. Allerdings liefen
manche Kartenfabrikate nicht, vor allem irgendwelcher Noname-schrott ala
"extreme-memory". Billige Karten reagieren recht sensibel auf allzu
"verwaschene" Signale.
Sichere 8 MHz mit AVR erreicht man mit niederohmigeren Widerständen.
Also nicht im Bereich 1,8/3,3 KOhm, sondern zum Beispiel 330/620 Ohm.
Bedeutet natürlich eine höhere Strombelastung, aber die Flanken werden
wieder steiler und somit ist eine höhere Frequenz möglich.
Auf "wundersame" Weise funktionierten danach auch Karten, die sich
vorher niemals haben ansprechen lassen ;-)
Bei 12Mhz ist mit der Spannungsteilerlösung so ziemlich Schluss.
Aber die werden mit einem AVR eh nicht erreicht.
Wenns also billig sein muss und der AVR unbedingt an 5V laufen muss,
dann funktioniert diese Lösung in jedem Fall.
Mittlerweile arbeite ich mit ARM und da tritt das Problem
glücklicherweise nicht mehr auf :-)
Joachim
joachim: danke fuer die ausfuehrungen. werd mal mit dem hardwareaufbau
herumexperimentieren.
den code hab ich mir natuerlich angesehen != verstanden.
bei elm chans software blick ich leider noch weniger durch.
mfg
Hansl
Hat noch jemand die ursprünglichen AtMega8 Sourcen für ein FAT
Filesystem und
kann er die Hier im Forum zur Verfügung stellen?
Das Ganze soll als Basis für einen kompakten Datenlogger dienen.
Schon im Voraus vielen Dank.
Hansl:
Jetzt muss ich aber nochmal fragen: Du hast die Versorgung des Boards
auf 3,3V gesetzt und die Spannungsteiler dringelassen???
So interpretiere ich jedenfalls Dein vorletztes Posting.
Joachim
joachim:
jepp, hab ich. nach ein wenig gruebeln war mir dann klar das das topfen
ist :) und habs rausgenommen. mittlerweile hab ich die MMC karte bei
nem freund getestet und es hat sich herausgestellt das weder dessen
cardreader noch sein palm pilot mit dem ding was anzufangen weiss.
der palm meldet eine fehlerhafte karte, der windoofpc aeussert sich
nicht dazu.
hab heute um 5 euronen ne 128mb RS-MMC karte von Lexar, was auch immer
RS sein soll, gekauft und nen LT1086 CM-3.3 von nem fibrechanneladapter
gebrutzelt.
werde des naechtesns wenns klima wieder passt einen 2. versuch starten
:)
dann wieder mit spannungsteiler am SPI und 5V VTARGET.
mfg
Hansl
es ist verhext. immer noch die MMC/SD initialization failed
fehlermeldung :(
elektrisch sollte alles korrekt sein. mmc wird durch nen LT1086 CM-3.3
versorgt.
habs nun mal mit 330 und 650 Ohm widerstaneden als spannungsteiler
probiert aendert auch nichts. gestern hat die karte in nem cardreader
aufjedenfall einwandfrei funktioniert. also wenn ich die karte nciht
irgendwie beim aufbauen geschrottet hab sollte die nun funktionieren.
folgendes habe ich messen koennen(mieses multimeter):
CS (MMC PIN1, MCU PB4) 3.24V
DATA IN (MMC PIN2, MCU PB5) 3.24V
VCC (MMC PIN4) 3.27V
DATA OUT (MMC PIN7, MCU PB6) 4.74V
hab keinen schimmer woranns liegen koennte :(
achja, ISP kabel abziehen bringt auch nix.
weitere debuggingtips?
mfg
Hansl
Hast du einen 100nF C über die 3,3V direkt am Kartenslot?
Bei mir läuft seit fast zwei Jahren die folgende Beschaltung.
Der interne PULL-UP am MISO ist deaktiviert
Für Signale vom uC an die Karte (CS, MOSI, SCK)
3v3 ^
|
| |
| | 47k
| | 2k2
| _____
MMC/SD -----O-----_______------ uC (out)
|
| |
| | 3k9
| |
|
GND
Data-Out der Karte (MISO)
3v3 ^
|
| |
| | 47k
| | 330
| _____
MMC/SD -----O-----_______------ uC (MISO)
werner:
hab nun auch deine schaltung aufgebaut, und in Rolandscode
noch ein PORTB &= ~_BV(PB6); ergaenzt um den pullup des MISO
PORTS zu deaktivieren. ergebnis unveraendert.
ich vermute das irgendwo am stk500 der hund begraben liegt...
nur wo?
dies ist nun der dritte aufbau. diesmal sogar mit 8Mhz internem takt!
und 100nf C am mmc. sicher ist sicher :)
anbei nochmal meine aktuellen fusesettings:
Fuse Low Byte = 0xd4
Fuse High Byte = 0xd9
Atmega16 @ 8MhZ, JTAG DISABLED
die mmckarte funktioniert. aufjedenfall hab ich das dintg gestern
nochmal getestet. leider aber nur mit einem palm :(
jemand irgendeine idee? ich tippe auf das stk500, denn das
ist das einzige an dem ich ausgenommen von "spi-programmingkabel
trennen" nix geaendert habe..
mfg
Hansl
aus dem, hey das guck ich mir schnell mal an ist mittlerweile ein
jahresziel geworden ;)
Tips hast Du bekommen, nur ob Du die umsetzt, ist fraglich.
Beim Lesen Deiner Beschreibungen kommt es einem so vor, als ob Du
"wahllos drin rumstocherst".
1. Besorg Dir ein Oszi und mess die SPI Leitungen. Gib dazu ein Muster
an SPI aus z.B. 0x5A und schau Dir die Signale SCLK und Data direkt an
der SD Karte an. Messe auch den Chip select.
Denk dran: Im Initmode darf die SD Karte maximal 400KHz bekommen.
Multimeter kasste vergessen. Man kann Hardware solange "blind"
programmieren, wie man Glück hat, dass alles klappt. Wenn aber der Wurm
drin ist, kommt man ohne das richtige Messzeug nicht weiter.
Wenn Du gar keine Chance hast, ein Oszi zu bekommen, dann bastel Dir
eine verbindung zwischen den Anschlüssen Data In und Data Out der
SD-Karte (natürlich solange diese NICHT eingesteckt ist :-) und mach
einen Loopback-test der SPI-Schnittstelle. Also ob das Byte, welches Du
sendest auch wieder reinkommt.
2. Gebe nach JEDEM Schritt ALLE empfangenen Daten der SD-Karte auf Dein
Terminal aus. Wenn gar nichts kommt, dann erzeuge zusätzliche
Hilfsmeldungen und sieh nach, WO in den Funktionen ein Timeout erfolgt.
Roland hat ja schon die UART implementiert, also wo ist das Problem?
Es geht nur Schritt für Schritt. Und immer nur EINE Sache ändern bzw.
testen, niemals MEHRERE gleichzeitig. Das ist extrem wichtig.
Und um Himmels Willen - besorg Dir irgendein billiges Oszi ;-)
Joachim
joachim:
zu 1:
oszi hab ich keins, kenn niemanden mit einem und kann ich mir auch
dieses jahr wohl sicher keines leisten.
loopbacktest, klingt einleuchtend, mal sehn ob ich dazu code finden
kann.
zu 2:
das mit dem code aendern ist ja nicht so einfach wenn man nicht
versteht was da genau passiert. vorallem besteht bei mir eher die
gefahr das der code wenn ich drinn ein wenig rumruehre ploetzlich
nichtmehr tut und dann faengt das "wahllos herumstochern" erst an.
ein paar printfs in "uint8_t sd_raw_init()" waern schon praktisch.
mal gucken wie ich das angehen koennte. das Jahr ist ja noch lang :)
hab wohl immer eine sache geaendert :) mal die widerstaende
ausgetauscht.
dann mal den takt geaendert, dann mal nen kondensator dazu, dann mal ne
neue MMC karte ran.....worauf willst DU HINAUS? (caps konnt ich mir ned
verkneifen ;))
mfg
Hansl
> loopbacktest, klingt einleuchtend, mal sehn ob ich dazu code finden> kann.
Wirst Du kaum. Musst Du selber programmieren.
Aber es gibt sicher irgendwo Basisroutinen zum Schreiben und Lesen eines
Wertes an/von SPI.
Um möglichst die originale Initialisierungssequenz zu nehmen, müsstest
Du den Loopbacktest hier einfügen (in der Main.c):
/* setup sd card slot */
if(!sd_raw_init())
{
#if DEBUG
uart_puts_p(PSTR("MMC/SD initialization failed\n"));
#endif
// HIER DEN LOOPBACK TEST
return 1;
}
Da beim betrieb ohne Karte und gebrücktem DIN/DOUT die Fehlermeldung
natürlich vorprogrammiert ist, muss der Test genau hinter der
Fehlermeldung rein. Der Vorteil: Du kannst die vorhandene SPI-Init
nehmen.
> das mit dem code aendern ist ja nicht so einfach wenn man nicht> versteht was da genau passiert.
Du sollst ja nicht sehr viel ändern, sondern nur ergänzen!
Der Trugschluss bei solchen Fremdprojekten ist, dass man sich die Arbeit
sparen kann. Das geht, wenn man Glück hat und alles funktioniert (was in
den seltensten Fällen so ist).
Wenn man aber hängt, braucht man viel Zeit, durchzusteigen.
Da solche Projekte meist schon sehr weit gediehen und optimiert sind,
und mit allen möglichen Features ausgestattet, ist es sehr schwer, die
relevanten Punkte herauszulesen. Man braucht oft lange, herauszufinden,
WO WAS und WARUM definiert ist.
Geht mir auch nicht anders. Da muss man durch.
Ich mache es aber so: Wenn etwas absolut nicht laufen will, dann
schreibe ich mir erstmal ein paar eigene Testprogramme für die Hardware.
Erst wenn diese erfolgreich verlaufen, kehre ich wieder zum Projekt
zurück.
Ich würde vorschlagen, Du vergisst erst mal die Sd-Karte und beginnst
damit, die SPI-Schnittstelle selber mal zu programmieren (einen besagten
Loopbacktest zu schreiben).
Wenn das dann funktioniert, kannst Du wieder zur SD-Karte zurückkehren.
Joachim
Hallo,
hab nun ein wenig herumkopiert und sende nun 0XFE als testwert.
scheine es aber nie zu empfangen.
hab ich da einen offensichtlichen fehler drinne?
oder ist meine hw total hinueber?
mfg
Hansl
anbei das gaenderte main.c aus sd-reader_source_20070603
dabei handelt sichs eiegentlich nur um einwenig copy&paste
aus sd_raw.c.
> hab vergessen das ueberfluessige zeug auszukommentieren
Ahaaa ;-)
Na also, nachdem Deine SPI nun sendet und empfängt, musst Du sehen, ob
das Chipselect signal für die Karte anliegt.
Das kann man leider nicht simulieren sondern nur messen.
Checke auch, ob Du den richtigen Port für das Selectsignal eingestellt
hast.
Das Select ist definiert in der sd_raw_config.h für die verschiedenen
Kontrollertypen:
#define select_card() PORTB &= ~(1 << xxxx)
#define unselect_card() PORTB |= (1 << xxxx)
Desweiteren würde ich für den Anfang die hohe Taktrate für die SPI
abschalten und folgende Zeilen auskommentieren (in sd_raw_init() in der
sd_raw.c). Das kannst Du gleich tun. Es beeinflusst die Gesamtfunktion
nicht, schützt Dich aber vor weiteren möglichen Hardwareproblemen.
/* switch to highest SPI frequency possible */
SPCR &= ~((1 << SPR1) | (1 << SPR0)); /* Clock Frequency: f_OSC / 4
*/
SPSR |= (1 << SPI2X); /* Doubled Clock Frequency: f_OSC / 2 */
Erst wenn die Karte komplett läuft, gibst Du dies wieder frei.
Läuft die Karte DANN nicht mehr, kannst Du sicher sein, dass Dein
Interface den hohen Takt nicht veträgt und die Signale "verwaschen".
Tja - viel mehr fällt mir dann auch nicht mehr ein.
Joachim
Immer noch kein Licht am Ende des Tunnels :(
Hab nun fogendes Setup:
STK500 auf 3.3V konfiguriert, Atmega16 @ 8MhZ, JTAG deaktiviert
ISP KABEL abgesteckt!
Hardwaresetup:
PORTB4 ------- CARDSELECT, PIN1 (gemessen 3.3V)
PORTB5 ------- DATAOUT, PIN7
PORTB6 ------- DATAIN, PIN2
PORTB7 ------- CLOCK, PIN5
VTG ---------- VCC, PIN4 (gemessen 3.3V)
GND ---------- GND, PIN3 & PIN6
Software anbei. (Mit den von Jochaim empfohlenen Aenderungen)
falls irgendjemand noch ne idee hat worans liegen koennte...bitte
schreien!
werd mir falls da nix mehr zu debuggen geht wohl oder uebel ne
platine aetzen und das ganze mal ohne stk500 probieren.
mfg
Hansl
Du weiss aber schon, dass bei dem Projekt 2 weitere Leitungen verwendet
werden, mit denen die GESTECKTE Karte (SD_available) und der
SCHREIBSCHUTZ (SD_Locked) abgefragt werden?
Der Schreibschutz ist erstmal unnötig.
In der sd_raw_config.h ist der Port fürs Erkennen der Karte definiert:
joachim:
noe hatte ich tatsaechlich uebersehn.
hab deine vorschlage alle ausprobiert.
der hund ist leider immer noch drinn. die lexar karte funtioniert
hier garnicht. eine 32mb nonamekarte eines freundes ergibt alle
heiligen zeiten mal die meldung "opening partition failed".
(power on, power off, power on, reset, reset....in irgendeiner
reihenfolge und so oft man lust dazu hat)
allerdings nur dann wenn ich PORTB &= ~_BV(PB6); also den internen
pullup des MISO aktiviert habe. wenn ich das rausnehme bekomme
ich die klassische..NIX DRANN meldung.
ich werd wohl wie geplant demnaechst ne platine aetzen und das
stk500 als fehlerquelle eliminieren.
mfg
hansl
Sehe ich das richtig? Ist die Standard Port-Belegung genau so wie bei
dem ISA-Ctrl Webserver? Kann ich das so auf der Platine nutzen ohne
irgendwelche Änderungen?
@roland riegel
hi
ich habe dein testprogramm kompiliert und auf einen ATMega128
geschrieben. Ich kann damit auf anhieb eine 64 MMC karte auf anhieb
ansprechen, beschreiben und lesen.
Ich danke dir für so ein tolles programm, jetzt muss ich mir es nurnoch
genauer angucken und verstehen.
Testbedingungen:
ATMega128 mit 6MHz, noname 64 MB MMC an Hardware-SPI
Ich verwende Rolands (Danke!) Code als Basis für eine eigene extrem
resourcengeizige MMC/SD-Anbindung an einen Mega8.
Die MMC-Karten sind noch unterwegs, in der Zwischenzeit habe ich mit
Transcend 1GB miniSDcards (lagen noch von einem anderen Projekt herum)
angefangen.
Folgende Zugriffe auf die Karte funktionieren: Init (modifiziert, nun
ohne sd_raw_available und CMD_SET_BLOCKLEN==16) /
CMD_SEND_CID/CMD_SEND_CSD.
Folgende Probleme treten auf
1) Single-Block Lesezugriff funktioniert auf volle Sektorvielfache
(512byte). Bei Blockzugriffen auf Startadressen die nicht & ~0x1FF sind
hängt sich die Karte auf, keine Fehlermeldung.
2) die Adressierung auf der Karte hat einen Offset von 0x1FE00. D.h. der
MBR erscheint bei 0x1FE00, der Rest ist entsprechend verschoben, aber
sektorweise korrekt lesbar.
In der SanDisk MMC Doku habe ich auf dieses Verhalten keinen Hinweis
gefunden, die Karte kann laut CSD bit79 partielle Zugriffe
(READ_BL_PARTIAL).
Frage: hat jemand eine Idee ob das mit dem Offset an der SD liegt? Ich
benötige die partiellen Zugriffe, um mit ganz weng SRAM schnell ein paar
Bytes zu bekommen (waveform von SPI-MMC abspielen, über SPI-DAC,
22050kHz Samplerate).
> ..und CMD_SET_BLOCKLEN==16)
Wo gibts das? Ich sehe nur:
#define CMD_SET_BLOCKLEN 0x10
und das bedeutet nichts anderes, als dass der Kommandocode für
SET_BLOCKLEN 0x10 (CMD16) ist. Und das schmeisst Du raus???
> 1) Single-Block Lesezugriff funktioniert auf volle Sektorvielfache> (512byte). Bei Blockzugriffen auf Startadressen die nicht & ~0x1FF sind> hängt sich die Karte auf, keine Fehlermeldung.
Es sind gemäß Grundeinstellung keine Lesezugriffe kleiner als 512 Bytes
erlaubt. Siehe:
1
/* set block size to 512 bytes */
2
if(sd_raw_send_command_r1(CMD_SET_BLOCKLEN,512))
Wenn Du die Startadresse nicht auf den Sektorstart legst, jedoch eine
Blockgröße von 512 eingestellt ist, kommt es zu einem Sektorüberlauf
(Read Block Misalignment).
> Frage: hat jemand eine Idee ob das mit dem Offset an der SD liegt?
Nein.
Der Offset ist eine Eigenschaft des FAT-Filesystems.
Der MBR liegt nie gleich am Anfang der Karte.
In der Partitionstabelle ist der Offset angegeben, z.B.
"Sectors preceding partition 1: 237"
Der MBR liegt also in diesem Fall bei 0x1DA00
Joachim
Hi
ich habe mal eine kleine zusammenfassung geschrieben für Roland Riegels
MMC/SD FAT16 code.
hoffendlich hat Roland Riegel nichts dagegen. und vieleicht hilf das ja
einen weiter.
Hallo,
ich verwende Rolands Code auf einem ATmega32 und möchte sehr viele Daten
in vielen Dateien auf einer MMC schreiben - möglichst schnell.
Ich habe eine Testroutine erzeugt, welche 1000 Dateien mit der Größe 1kB
erzeugt, alle im Root-Verzeichnis. Zum Debuggen lasse ich mit
ausfühliche Infos per UART zum PC senden. Mir ist aufgefallen, dass
schon nach ein paar Dateien das Erstellen und Öffnen der Dateien sehr
lange (1 bis 5 Sekunden) Dauert. Ist das normal? Kann man das ganze
beschleunigen? Würde es schneller gehen, wenn man Unterordner anlegt und
darin die Datei schreibt?
michi
>Ich habe eine Testroutine erzeugt, welche 1000 Dateien mit der Größe 1kB>erzeugt, alle im Root-Verzeichnis.
Bei FAT12 und FAT16 kann man maximal 512 Dateien im RootDir anlegen.
Wenn sie nur 8.3 DOS Dateinamen haben jedenfalls. Mit
langen Dateinamen sind es höchstens noch die Hälfte. Eher weniger.
Wenn du 1000 Dateien anlegen willst musst du ein
Unterverzeichnis anlegen und dort die Dateien schreiben.
Das mit den 512 Dateien ist klar, aber die Geschwindigkeit wurde schon
nach 50 bid 80 Dateien im Root-Verzeichnis beachtlich langsam. Wo müsste
man denn ansetzen um den Code von Roland zu optimieren?
Ich habe mehrere tausend Messungen mit unterschiedlichen Datensätzen und
Längen.
Diese sollen direkt weiter verarbeitet werden können, ohne den Umweg
über ein Tool, was eine große Datei erst wieder auseinander nehmen muss.
Eventuell erstelle ich schon vorher leere Dateien und lasse sie
geöffnet. Das sollte doch problemlos möglich sein, auch wenn der
Controller zwischendurch im Powerdown-Mode und die Karte ausgeschaltet
wird oder?
>Eventuell erstelle ich schon vorher leere Dateien und lasse sie>geöffnet.
Wo merkst du dir für ein paar tausend offene Dateien z.B.
den Startcluster ? Der ist mindestens 16 Bit. Bei 1000
Dateien brauchst du also schon mal min. 2kB RAM. Dann musst du dir
noch merken an welcher Dateiposition du bei jeder Datei bist.
Pro Position 32 Bit. Bei 1000 Dateien noch mal 4kB.
Das war aber noch nicht alles was du dir merken musst :(
Dein Konzept ist nicht realisierbar.
>Wo merkst du dir für ein paar tausend offene Dateien z.B.>den Startcluster ? Der ist mindestens 16 Bit. Bei 1000>Dateien brauchst du also schon mal min. 2kB RAM. Dann musst du dir>noch merken an welcher Dateiposition du bei jeder Datei bist.>Pro Position 32 Bit. Bei 1000 Dateien noch mal 4kB.>>Das war aber noch nicht alles was du dir merken musst :(>Dein Konzept ist nicht realisierbar.
Doch, es sind nur ca. 10 Dateien gleichzeitig offen, eben 10 für jede
Messung. Es werden pro Messung also 10 Dateien erstellt und es gibt
später einige 1000 Messungen.
Ich hatte mich etwas unglücklich ausgedrückt, sorry.
Blöderweise bekomme ich sehr viele Daten in kurzer Zeit, so dass ich für
jede geöffnete einen Buffer von min. 512 Byte brauche, damit es
überhaupt mit dem Schreiben voran geht. Bei 4kB geht aber auch das
nicht.... ich brauch ein neues Konzept.
Aber nebenbei mal: Rolands Code ist wirklich klasse!
Hello!
I hope that it is OK to post questions in English. I have a Atmega16 and
STK500 evaluation board, using the software generated clock at 3.68Mhz,
all is operating at 5V.
I haved used Rolands hardware connections and source code for
interfacing SD card. UART working fine, but it is not possible to get
any SD card to be accepted. 3 different types of SD cards has been
tested, Toshiba 16MB, Kingston 1GB and RiData 512MB. The code is stopped
at different positions depending on which card is used. 16MB cards is
stopped when setting the block size to 512b, 512MB card stops after the
verifing the FAT parameters, data_cluster_count is always larger than
65525. 1GB card stops in this loop
1
while(sd_raw_rec_byte()!=0xfe)
located in SD_RAW.C anyonelse got similar problems?
I think the problem for this is the partition table or what do you
think?,
I have used FDISK to create partitions for "06 FAT16" should it be
primary or logic? and then format it in which way?
Regards
Niklas
Hallo, hab das Filesystem in den Griff, hab nur probleme mit dem
Stromverbrauch.
Wenn die Karte in den Schacht geschoben wird ist alles ok.
Jetzt wird die SD Karte initialisiert, beschrieben, gelesen, usw.
Dafür brauche ich so ca. 40 mA, alles ok.
Nachdem allerdings alle Vorgänge beendet sind, bleibt der Stromverbrauch
bestehen.
Gibt es einen Befehl, eine Möglichkeit, die SD Karte zurück in den
Standby Modus zu bringen ?
IIRC geht nach Spezifikation jede SD Karte nach einiger Zeit der
Inaktivität automatisch in den Standby. Man muss nur den Chip-Select
wegnehmen (und den Takt?). Eventuell liest du die Karte nicht
vollständig aus (Dummy-CRC etc.)
Ich schicke der SD Karte in meinen Programmen am Ende immer noch ein
Dummy-0xFF, nehme den Chipselect weg und schicke noch ein 0xFF um der
Karte einen Takt zum "Runterfahren" zu geben.
@ Niklas Eriksson,
I got similar problems, I use a different Compiler (CrossStudio for AVR)
I made some wrong settings (Datastacksize - was too small, and I used
some Compiler-Optimization (10 hours of my life 4 nothing :-) ))
best regards
KL
I used the roland-riegel sd/mmc AVR source with atmel128, 16 Mhz.
(version 2007.01.20)
http://www.roland-riegel.de/sd-reader/index.html
It is good 512Mb SD/MMC cards, but 64 Mb and 128Mb is bad.
Why?
best regards
Istvan Tiszai from Budapest
Hallo,
bin neu hier. Habe ein SD-Projekt welches seid jahren läuft. Jetzt tritt
bei einem neuen Typ SD-Card (256MB PLATINUM) das Problem auf das beim
lesen eines Blocks (Sektors Byte 0-511 +2CRC) an Stelle Byte5 immer die
0x04 gelesen und beim lesen vom MBR an Stelle Byte4 0x0F im Root bei
Byte4 die 0x3F und im Bootsektor bei Byte4 die 0x5F gelesen werden. Das
ist mit allen Karten diesen typs so. Mit Cardreader gelesen ist aber
alles ok. Bei anderen Karten wie EXTREMEMORY habe ich das Problem nicht!
Hat jemand ne Ide??
Es kann am SPI-Signal selbst liegen. Manche Karten reagieren
empfindlicher auf langsame Flanken. Ich hatte so ein Problem auch bei
einer Serie von SanDisk Karten. Die waren (mit dem
Spannungsteileraufbau) nicht zu gebrauchen. Bei einem neuen Design mit
3,3V Logik (steile Flanken) funktionierten die plötzlich auch. Bei hoher
Taktrate kann es passieren, dass die Pegel nicht mehr ganz auf VCC bzw.
GND gehen, sondern irgendwo "in der Luft hängen". Manche Karten vetragen
das besser als andere.
Ich würde mir mal die SPI-Signale anschauen. Wenn die "verwaschen" sind,
die Widerstandswerte für den Spannungsteilen reduzieren. Dann werden die
Flanken steiler und es könnte wieder klappen.
Joachim
Hallo Roland,
Habe Dein Programm getestet.
Erste Erfahrugen waren ausreichend, grösseren Dateien zu SCHREIBEN ist
es aber wahnsinnig langsam.
(Habe beim Schreiben eines Datenblock zum UART ein '.' gesendet. :))) )
Mit 1Mbyte Dateigrösse geht es so: am Anfang laufen die Punkte
blitzschnell, am Ende kommen nur "Schrittweise".
Eine Datei von 50-100kByte geht es in ca. 10 Sekunden, 1Mbyte zu
schreiben dauert aber ca. 4(!) Minuten! Das ist gar nicht linear (u.
akzeptabel).
Habe ein bisschen im Programm nachgeforscht, es sieht so, dass bei der
Clusterallokation ist was irgendwie zu langsam.
Oder?
Kannst Du mir was dazu sagen?
Vielen Dank,
Karoly
Hallo,
auch ich bin derzeit ein wenig am probieren. Grundsätzlich funktioniert
auch alles (eher selten bei mir) - solange es in der Hauptschleife läuft
(main).
Jetzt wollte ich mir ein paar Funktionen anlegen, um etwas Struktur in
den Code zu bringen.
Bis jetzt ist es mir nicht gelungen, die Dateioperationen, in einer
Funktion zum Laufen zu bewegen.
Ausgehend vom beiliegend Beispiel main.c -> sd-reader.hex habe ich den
Part print_disk_info(fs) in eine Funktion geschrieben und selbige im
main auskommentiert.
Original:
1
intmain()
2
{...
3
/* print some card information as a boot message */
4
print_disk_info(fs);
5
...}
Versuch:
1
voidtest(void);
2
intmain()
3
{...
4
/* print some card information as a boot message */
5
//print_disk_info(fs);
6
test();
7
...}
8
9
voidtest()
10
{
11
print_disk_info(fs);
12
}
Hoffe, es ist einigermaßen verständlich.
Als Fehlermeldung erhalte ich :
error: 'fs' undeclared (first use in this function)
Im Moment trete ich auf der Stelle und weiß nicht so recht, wo ich
ansetzen kann/soll.
Viele Grüße
Stephan
Hallo Stephan!
Schaue bitte in jedes beliebige Buch oder Online-Tutorial, welches eine
Einführung in C liefert. In Deinem Fall ist da insbesondere der
Abschnitt über den Gültigkeitsbereich von Variablen interessant.
Die Fehlermeldung des Compilers sagt eigentlich schon alles. Kurz
gesagt: Die Variable fs, die Du der Funktion print_disk_info()
übergibst, muss in der aufrufenden Funktion test() oder zumindest im
globalen Gültigkeitsbereich auch existieren.
Gruß,
Roland
Hallo Karoly!
Nun, FAT16 ist insgesamt relativ ineffizient, vor allem mit wenig
Pufferspeicher. Das nur vorweg.
Ansonsten solltest Du bzgl. meines Codes auf mehrere Dinge achten:
- SD_RAW_WRITE_BUFFERING unbedingt auf 1 stellen.
- Wenn reichlich RAM bereitsteht, den Schreib-/Lesepuffer vergrößern
(nur mit manuellen Codeänderungen möglich).
- Der Datenblock, der fat16_write_file() übergeben wird, sollte
möglichst groß sein.
- Statt immer an das Ende der Datei zu schreiben, zu Beginn
fat16_resize_file() aufrufen, danach ab Position 0 die Datei füllen. Das
sollte die abwechselnden Schreibzugriffe auf die FAT, die Datei-Cluster
sowie den Verzeichniseintrag unterbinden, so dass SD_RAW_WRITE_BUFFERING
wesentlich besser greifen kann.
So, ich denke das sollte Dir erst mal weiterhelfen.
Gruß,
Roland
Hallo,
ich versuche mich auch gerade bei der SD-Ansteuerung an einen
ATmega324P. Als Levelshifter dient der MAX3378E, die 3.3V liefert ein
extra Spannungsregler.
Bei der SD Karte handelt es sich um eine SanDisk 1GB Standard (Rd/Rw:
3MB/s)
Die Funktion sd_raw_init() funktioniert fehlerfrei, es wird jedoch nicht
das Filesystem (FAT16) der SD-Karte erkannt. Nach dem Einlesen des FAT16
Headers springt er zurück, da sectors_per_fat = 0.
Nun habe ich schon vielerlei Formatierungen ausprobiert, über die
Datenträgerverwaltung (Format mit "FAT") und mkdosfs sowie eine
Low-Level-Formatierung mit dem Panasonic SD Formatter und anschließender
Windows-Formatierung. Auslesen der SD Karte mit WinHex zeigte, dass in
allen Fällen ein FAT16-System erfolgreich angelegt wurde. Nur der
Controller will dies nicht so recht glauben.
Noch etwas: Lasse ich alle Initalisierungsroutinen in der Endlosschleife
laufen, erkennt er im zweiten Durchlauf auch nicht mehr die Partition.
Direkt nach dem Controllerreset versucht er zumindest, das Filesystem
zu öffnen.
Woran kann das liegen?
Danke im Voraus
Gruß Micha
Ich habe mich letzte Nacht auch mit dem Anschluß von SD-Karten bespasst,
daher sind meine Erfahrungswerte noch recht frisch ;)
sectors_per_fat = 0 konnte ich dadurch beheben, daß ich erst die
Partition -1 versuche und dann 0 - in umgekehrter Reihenfolge zu dem
Beispiel-main.c
Das Problem mit den mehreren Durchläufen hatte ich auch. Du mußt die
verschiedenen Pointer wieder freigeben (partition_close, fat16_close
etc.), dann klappt es auch mit den mehrfachen Durchläufen.
Gruß,
Kai
Hallo Kai,
danke für deine schnelle Hilfe, mein Initialisierungsproblem ist auch
fast gelöst. Tatsächlich lässt sich Partition 0 nicht öffnen, folglich
versucht er Partition -1 (Originalcode), was dann auch klappt. Danach
lässt sich jedoch nicht das Filesystem öffnen. Lasse ich jedoch die
Initalisierung erneut ablaufen (nach Pointerfreigabe, also
partition_close() und fat16_close()) liest er plötzlich Partition 0
erfolgreich und erkennt auch ein FAT16 Dateisystem! Was ist denn nun
passiert?
Kehre ich die Partitionsreihenfolge um, wie du vorgeschlagen hast,
öffnet er das FAT16 nicht (nicht mal nach mehreren Durchläufen).
Gruß Micha
Einige Anmerkungen:
Partition -1 zu öffnen klappt immer. Das liegt aber daran, dass er die
Karte in diesem Fall als Superfloppy (d.h. als einziger Datenbereich
ohne Partitionstabelle) behandelt und deshalb auch keine Überprüfungen
bzgl. der Existenz der Partition machen kann.
Es ist also kein Zeichen von "Erfolg", wenn Partition -1 geöffnet werden
kann. Auf dieser ein Dateisystem zu öffnen klappt aber hingegen nur,
wenn die Karte auch wirklich als Superfloppy formatiert ist.
Wenn also schon das Öffnen der Partition 0 scheitert, liegt dies nur
an der Partitionstabelle, entweder weil die Partition nicht existiert,
die Partitionstabelle fehlerhaft ist oder diese nicht existiert.
Unter Linux klappt die Formatierung einer Karte so:
1. Karte einlegen.
2. Im Syslog nachschauen, unter welchem Namen sie eingebunden wurde.
Annahme für die weiteren Schritte: /dev/sdc.
3. fdisk /dev/sdc
o (Partitionstabelle löschen)
n (neue Partition)
p (primäre Partition)
1 (<-- eine Eins; erster Eintrag in Partitionstabelle)
<Enter>
<Enter> (Partition über gesamte Karte)
t (Partitionstyp ändern)
6 (Typ: FAT16)
p (Partitionierung ausgeben; überprüfen!)
w (Partitionstabelle schreiben)
4. mkdosfs -F 16 /dev/sdc1 (<-- auf die Eins am Ende achten)
Windows erzeugt meines Wissens nach eine Superfloppy.
Grüße,
Roland
Ich habe gestern auf jeden Fall meinen Code derart erweitert, daß ich
erst Partition 0 öffne und versuche auf das FAT16 zuzugreifen. Schlägt
dies fehl, dann close ich Partition 0 und versuche es mit Partition -1.
Erst wenn dies fehlschlägt, dann gibt es einen Fehler.
Damit konnte ich erfolgreich alle (10 verschiedene) SD-Karten, derer ich
habhaft werden konnte und die auf verschiedenen Geräten/OSen formatiert
wurden, lesen.
Ich habe aber noch ein paar Modifikationen an Roland's Code durchgeführt
:
- Software SPI - umschaltbar HW SPI / SoftSPI per #define im Header-File
- An ein paar Stellen while (result = 0xfe); ersetzt durch eine
Schleife, welche ein definiertes Ende hat
- FAT32-Support angefangen zu implementieren (auch Header-File Option)
Werde Roland mal einen Patch zukommen lassen - mal sehen, ob er die
Änderungen gebrauchen kann.
Hallo Kai,
> Ich habe gestern auf jeden Fall meinen Code derart erweitert, daß ich> erst Partition 0 öffne und versuche auf das FAT16 zuzugreifen. Schlägt> dies fehl, dann close ich Partition 0 und versuche es mit Partition -1.> Erst wenn dies fehlschlägt, dann gibt es einen Fehler.
Nun, das ist doch genau das Vorgehen, welches ich in meinem Code
verwende?
> - FAT32-Support angefangen zu implementieren (auch Header-File Option)>> Werde Roland mal einen Patch zukommen lassen - mal sehen, ob er die> Änderungen gebrauchen kann.
Schön. Dazu dann alles weitere per Mail.
Gruß,
Roland
> Schön. Dazu dann alles weitere per Mail.
Hhm. Interessiert wäre ich auch, schade das ihr das nicht öffentlich
macht.
Btw: Mein modifizierter SD-Reader funktioniert seit knapp einem Jahr im
Dauereinsatz tadellos.
:-)
Torsten
Hallo Torsten,
>> Schön. Dazu dann alles weitere per Mail.>> Hhm. Interessiert wäre ich auch, schade das ihr das nicht öffentlich> macht.>
Nunja, das wird eh kaum in näherer Zukunft in meinen Code kommen, weil
mein kleiner mega168 eh schon mit knappem Speicher kämpft, und von dem
braucht FAT32 schon ein gutes Stück mehr. Da müsste ich mir also einen
anderen Aufbau z.B. mit mega32 oder gleich einem ARM überlegen.
Aber ich denke, Kai ist auch bereit den Patch hier im Forum zu posten...
> Btw: Mein modifizierter SD-Reader funktioniert seit knapp einem Jahr im> Dauereinsatz tadellos.>
Schön zu hören!
Gruß,
Roland
Sollte den Code nicht größer machen, wenn man FAT32_SUPPORT 0 setzt.
Root-Directory klappt schon.
Freier Speicher auch fertig.
Werde mich nun gleich noch einmal kurz an die
Cluster-FAT32-Verkettungsroutinen setzen. War wohl gestern zu blind um
den Fehler zu sehen 8)
Nevertheless, ja, klar kann (und werde) ich den Patch dann hier auch
veröffentlichen.
Anbei der angekündigte Patch. Ist leider doch etwas mehr Modifikation
geworden ...
Auf jeden Fall sollten SDHC-Karten und FAT32 funktionieren. Die
SDHC-Initialisierung habe ich derzeit nicht Präprozessorgesteuert
gemacht. FAT32 support kann im Header-File deaktiviert werden.
Ich hoffe ich habe den Code soweit gut genug aufgeräumt - es waren doch
intensivere Debug-Sessions nötig, welche einige debug()-Calls nach sich
gezogen haben.
Sollte aber alles "DEBUG_FAT16, DEBUG_SD, DEBUG_PARTITION" bzw.
"VERBOSE_FAT16, VERBOSE_SD, VERBOSE_PARTITION" geklammert sein und daher
bei nicht existenten Defines sauber kompilieren.
Im partition.c habe ich außerdem die Partitionserkennung/-prüfung
erweitert.
Mit den Berechnungen (block >> 9), (block_offset) beim Aufrufen der
sd_raw_* void*-Funktionspointer, bin ich noch nicht ganz glücklich. Wenn
jemand eine bessere Idee hat ... der Code ist ja nun passend zu den
Feiertagen ...
Viel Spaß! :)
Kai
Wow, exzellente Arbeit!
Ich habe mir das diff-file nur kurz angeschaut. Mehr als 3400 Zeilen,
einige neue Dateien. Unmöglich das per Hand in mein Projekt fehlerfrei
einzubauen um das mal auszuprobieren.
Deswegen meine Frage: Wenn es Dir nichts ausmacht, kannst Du vielleicht
den SD-Reader inklusive der neuen Sachen in ein .zip packen und hier
veröffentlichen?
Der Patch ist ein richtig dicker Brocken... Welche MCU hattest Du zum
debuggen, wegen Ram etc.?
Torsten
Danke für das positive Feedback :)
Ich wollte Roland eigentlich erst einmal die Entscheidung zum Einbau
überlassen.
Kann aber sonst auch gerne mal ein komplettes Zip-File als
"FAT32-Version" hochladen.
Neue Files sollten eigentlich nicht drin sein. Habe gerade auch noch
einmal in den Patch gesehen und konnte keine finden. Welche neuen Files
versucht er denn bei dir zu erstellen?
Zum debuggen habe ich ein m2561 mit S65-Display verwendet. Den
zusätzlichen Speicherverbrauch habe ich auch noch nicht überprüft -
hatte hierbei auch auf Roland gehofft, da er ja wohl eine passende
Referenz-Plattform zur Verfügung hat und die Werte daher auch einfacher
mit seinen vergleichen könnte. (ich hoffe der Code ist nicht zu groß für
die von ihm verwendete CPU geworden)
Grundsätzlich sollte man natürlich auch die Nachteile von FAT32
bedenken. Der deutlich größere FAT-Table verursacht natürlich einiges an
Kosten auf der CPU und auf dem SD-Interface. Die Überprüfung auf freien
Speicherplatz (FAT16/FAT32) verdeutlicht dies auch eindrucksvoll.
Mit mehr Speicher sähe die Situation anders aus - nicht für den
Speicher, aber für die Performance ;)
Vielleicht komme ich ja noch dazu einen Patch für 32 oder 64k zu machen.
64k (56k nutzbar) wären für mich sehr elegant, da man dann auch über
ein performates .png deflate nachdenken könnte, was für mein Projekt
sehr nett wäre. Schaue mir gerade mal die zlib an ...
Kai Bankett wrote:
> Danke für das positive Feedback :)
Gerne. Kein Anfängerwerk btw.
> Neue Files sollten eigentlich nicht drin sein. Habe gerade auch noch> einmal in den Patch gesehen und konnte keine finden. Welche neuen Files> versucht er denn bei dir zu erstellen?
Oops, Du hast recht. Ich habe mich nur durch "-FAT32" irritieren lassen:
--- SD-Card/fat16.c
+++ SD-Card-FAT32/fat16.c
Wobei der Dateiname nun nicht mehr passt.
> Zum debuggen habe ich ein m2561 mit S65-Display verwendet. Den> zusätzlichen Speicherverbrauch habe ich auch noch nicht überprüft -
Mit diesem Monster sollte es keine Speicher-Probleme geben. ;)
> hatte hierbei auch auf Roland gehofft, da er ja wohl eine passende> Referenz-Plattform zur Verfügung hat und die Werte daher auch einfacher> mit seinen vergleichen könnte. (ich hoffe der Code ist nicht zu groß für> die von ihm verwendete CPU geworden)
Er ist mit Sicherheit zu groß. In einen M168 passt das nicht mehr rein.
> Grundsätzlich sollte man natürlich auch die Nachteile von FAT32> bedenken. Der deutlich größere FAT-Table verursacht natürlich einiges an> Kosten auf der CPU und auf dem SD-Interface. Die Überprüfung auf freien> Speicherplatz (FAT16/FAT32) verdeutlicht dies auch eindrucksvoll.> Mit mehr Speicher sähe die Situation anders aus - nicht für den> Speicher, aber für die Performance ;)
Das ist ganz klar. Alles hat seinen Preis.
Nun mache ich mir Sorgen ob das auch in einen M644 noch rein paßt. Einen
M32 mußte ich schnell ersetzen. Der hat zwar noch für den reinen
SD-Reader gereicht aber nicht mehr für Erweiterungen.
> Vielleicht komme ich ja noch dazu einen Patch für 32 oder 64k zu machen.> 64k (56k nutzbar) wären für mich sehr elegant, da man dann auch über> ein performates .png deflate nachdenken könnte, was für mein Projekt> sehr nett wäre. Schaue mir gerade mal die zlib an ...
Ähm, was meinst Du mit 32 oder 64k, SRAM oder Cluster-Größe etwa?
Ein paar typos habe ich auf die Schnelle gefunden:
Torsten S. wrote:
> Oops, Du hast recht. Ich habe mich nur durch "-FAT32" irritieren lassen:> --- SD-Card/fat16.c> +++ SD-Card-FAT32/fat16.c> Wobei der Dateiname nun nicht mehr passt.
Du mußt patch mit der Option -pX aufrufen, je nachdem in welchem
Verzeichnis du dich befindest. Sollte funktionieren, wenn du den Patch
in das Verzeichnis legst, in dem sich auch die zu patchenden Files
befinden und -p0 verwendest.
Auf jeden Fall ist es beim GNU-patch unter Unix so. Ich weiß ja nicht,
ob du diesen benutzt hast, sonst mußt du schauen, wie die Option zum
abschneiden des 1. Directories bei der von dir verwendeten Applikation
benutzt wird.
>> Er ist mit Sicherheit zu groß. In einen M168 passt das nicht mehr rein.>
Hm. Das ist schade. Man könnte natürlich noch Ballast rauswerfen. SDHC
z.B., wobei FAT32 dann natürlich nicht mehr wirklich Sinn macht.
> Das ist ganz klar. Alles hat seinen Preis.> Nun mache ich mir Sorgen ob das auch in einen M644 noch rein paßt. Einen> M32 mußte ich schnell ersetzen. Der hat zwar noch für den reinen> SD-Reader gereicht aber nicht mehr für Erweiterungen.
Wie gesagt, eindampfen kann man sicherlich noch. Ich müßte nur wissen,
wieviel fehlt. So viel ist nun auch wieder nicht dazu gekommen. Man
könnte sich natürlich nur auf FAT32 beschränken. Dann spart man sich
einen Teil dessen, was dazu gekommen ist.
> Ähm, was meinst Du mit 32 oder 64k, SRAM oder Cluster-Größe etwa?
War auf die Menge an RAM bezogen. Mit mehr Speicher kann man mehr
cachen. Den FAT komplett, oder auch nur teilweise, zu cachen würde eine
Menge bringen.
> Ein paar typos habe ich auf die Schnelle gefunden:>
Hallo zusammen,
ich versuche mich gerade daran, mit einem ATmega324P eine SD-Karte
anzusteuern; dabei verwende ich allerdings das USART im SPI-Modus
anstelle des regulären SPI, da ich dieses in meiner Schaltung
anderweitig benutze.
Schreiben und Lesen funktioniert im Prinzip: in einem ersten Versuch
habe ich mit sd_raw_write()/sd_raw_sync() 250 Byte auf die Karte
geschrieben und konnte die mit sd_raw_read() auch wieder lesen.
In meinem derzeitigen Programm rufe ich zunächst die Funktionen auf:
sd_raw_init();
partition_open(...);
fat16_open(...);
fat16_get_dir_entry_of_path(...);
fat16_open_dir(...);
dabei treten keine Fehler auf.
Dann versuche ich, eine Datei zu erzeugen und etwas hineinzuschreiben:
fat16_create_file(dd,"datei.tst",&dir_entry);
fd = fat16_open_file(fs,&dir_entry);
// fat16_resize_file(fd,1500);
fat16_write_file(fd,"Hallole!",8);
fat16_close_file(fd);
sd_raw_sync();
Die Datei wird zwar angelegt, sie wird beim Schreiben aber nicht
vergrößert. Kontrolle am PC zeigt eine Datei der Länge 0. Wenn ich die
nun am PC beschreibe, kann auch der Controller den String
hineinschreiben.
Der Aufruf von fat16_resize_file() hilft nicht weiter, da bleibt das
Programm hängen beim Aufruf von device_write() in
fat16_write_dir_entry() (Zeile 1764 in fat16.c)
Hat da jemand eine Idee, was da schiefläuft?
Danke im voraus
Martin
Hallo Martin,
Könntest Du bitte genauer sagen, wo sd_raw_write() hängen bleibt?
Des weiteren könntest Du versuchen herauszufinden, warum es nicht hängen
bleibt, wenn fat16_write_dir_entry() aus fat16_create_file() oder
fat16_write_file() heraus aufgerufen wird. Schalte doch mal für Deine
Tests SD_RAW_WRITE_BUFFERING aus, dann treten mögliche Schreibprobleme
sofort auf und nicht erst dann, wenn der Puffer geschrieben wird.
Ehrlich gesagt vermute ich eher ein Hardwareproblem. Aber mal sehen...
Gruß,
Roland
Hallo Roland,
das Problem tritt bereits bei fat16_create_file(), nur nicht so
offensichtlich. Ich habe gestern abend noch folgendes ausprobiert:
uint8_t result = 0;
if ( !fat16_create_file(dd,"datei.1",&dir_entry) ) result++;
if ( !fat16_create_file(dd,"datei.2",&dir_entry) ) result++;
if ( !fat16_create_file(dd,"datei.3",&dir_entry) ) result++;
if ( !fat16_create_file(dd,"datei.4",&dir_entry) ) result++;
if ( !fat16_create_file(dd,"datei.5",&dir_entry) ) result++;
if ( !fat16_create_file(dd,"datei.6",&dir_entry) ) result++;
if ( !fat16_create_file(dd,"datei.7",&dir_entry) ) result++;
if ( !fat16_create_file(dd,"datei.8",&dir_entry) ) result++;
if ( !fat16_create_file(dd,"datei.9",&dir_entry) ) result++;
sd_raw_sync();
if ( !result ) for (;;) PORTB ^= 0x0E; // alles ok
else for (;;); // Fehler!
Wenn ich SD_RAW_WRITE_BUFFERING eingeschaltet habe, wird nur datei.1
angelegt. Schalte ich dagegen SD_RAW_WRITE_BUFFERING aus, werden datei.1
bis datei.4 oder datei.5 erzeugt, außerdem datei.9. Aber nur unter
Linux sind die Dateien auch zu sehen, manchmal wird eine Datei auch
doppelt angezeigt! Windows zeigt nur ein leeres Verzeichnis an.
Da ich in Deinem Code die Funktionen sd_raw_init(), sd_raw_send_byte()
und sd_raw_send_byte() geändert habe, könnte natürlich auch hier irgend
etwas passieren, obwohl ich das weniger glaube, da ich das doppelt und
dreifach gegen das Datenblatt verglichen habe.
Ich habe mir gestern noch ein STK500 und eine Handvoll Controller
bestellt, die sind vorhin angekommen. Mal sehen, ob ich Deinen
Originalcode da zum Laufen bringe und da zu irgendeiner Erkenntnis
komme.
Gruß
Martin
Hallo Martin,
Mir fehlen einige Infos, um selbst irgendwas testen zu können.
1. Was ist denn der Wert von result in Deinem Test?
2. Kannst Du mir ein Karten-Image zukommen lassen?
3. Werden die Dateien im Wurzelverzeichnis oder in einem
Unterverzeichnis angelegt?
4. Wie hast Du denn die Karte formatiert? Du solltest die Karte nach
jedem Test löschen, so dass evtl. kaputte FAT-Strukturen nicht weitere
Effekte auslösen können.
5. Wie stark ausgelastet ist der Controller sonst? Besteht die
Möglichkeit von Stack-Überläufen?
Gruß,
Roland
Hallo Roland,
> 1. Was ist denn der Wert von result in Deinem Test?
Bei ausgeschaltetem SD_RAW_WRITE_BUFFERING hat result den Wert 0, obwohl
nicht alle Dateien angelegt werden. Im Fall von Doppeleinträgen, d.h.
wenn derselbe Dateiname zweimal angezeigt wird, erhalte ich den Wert 4.
Schalte ich SD_RAW_WRITE_BUFFERING ein, erhalte ich ebenfalls den Wert
0, wenn ich fat16_create_file() einmal aufrufe. Rufe ich die Funktion
zweimal oder öfter auf, bleibt das Programm hängen und ich komme erst
gar nicht zu meiner Endlosschleife, die erste Datei (datei.1) wird aber
angelegt.
Für die Tests habe ich die Karte jedesmal formatiert.
> 2. Kannst Du mir ein Karten-Image zukommen lassen?
Ich habe 1MB-Images von drei verschiedenen Karten angehängt, jeweils mit
(*-mb) und ohne (*-ob) Buffering.
> 3. Werden die Dateien im Wurzelverzeichnis oder in einem> Unterverzeichnis angelegt?
Die Dateien stehen im Wurzelverzeichnis.
> 4. Wie hast Du denn die Karte formatiert?
Mit mkdosfs -F16 /dev/sda1 unter Linux.
> 5. Wie stark ausgelastet ist der Controller sonst?
Im Moment dreht er nur Däumchen, d.h. ich setze lediglich ein paar
Port-Pins und versuche dann, die Karte anzusprechen, sonst passiert noch
nichts.
Gruß
Martin
Servus Martin,
Nach kurzem Überfliegen der Images kann ich schonmal soviel sagen:
1. Das was Windows und Linux anzeigen, ist plausibel und durch
geringfügig andere FAT-Implementationen erklärbar.
2. Ohne Pufferung fehlen die LFN-Verzeichniseinträge bzw. sind leer. Mit
Pufferung sind sie vorhanden.
3. Der Platz für die Verzeichniseinträge der fehlenden Dateien ist zwar
vorhanden, enthält aber auch nur Nullen.
4. Die doppelt vorhandenen Dateien sind so tatsächlich auch im
Verzeichnis eingetragen.
Da stimmt irgendetwas überhaupt nicht. Entweder die SD-Routinen geben
Erfolg zurück, obwohl nichts geschrieben wurde, oder es gibt einen Bug
an anderer Stelle. Wie machst Du denn die Stromversorgung und das
Level-Shifting für die Speicherkarte?
Magst Du mir vielleicht Dein Testprogramm inklusive der von Dir
durchgeführten Änderungen an sd_raw.c schicken? Evtl. fällt mir da noch
irgendwas auf.
Vielleicht finde ich morgen etwas Zeit, um Deinen Test nachzubauen und
evtl. den Fehler zu reproduzieren.
Viele Grüße,
Roland
Hallo Roland,
meine Schaltung läuft mit 3,3V; damit sollte die Karte eigentlich
zufrieden sein. Der externe Takt ist 18MHz, den internen Systemtakt habe
ich sicherheitshalber auf die Hälfte reduziert.
Mein Testprogramm habe ich angehängt, die Hauptänderungen sind in
sd_raw_init(), sd_raw_send_byte() und sd_raw_rec_byte() (s.
aenderungen).
Gruß
Martin
Hallo Martin,
Gestern konnte ich Deine Probleme teilweise reproduzieren. Bei mir
scheiterte allerdings nur das korrekte Anlegen der achten Datei. Nach
viel erfolglosem Debugging hat sich rausgestellt, dass (zumindest bei
mir) tatsächlich der Stack in den statisch allokierten Heap
reingewachsen ist.
Sobald ich nicht so viel Speicher verbraucht habe, indem ich z.B. die
Dateien nur noch einstellig benannt habe, lief alles so wie es sollte.
Ich habe mir mal Dein Programm bzgl. des benutzten Speichers angeschaut:
- Puffer
512+5 Bytes
- Handles für Partition, Dateisystem, Dateien, Verzeichnisse
17+26+51+94 Bytes
- Stack in main():
ca. 95 Bytes
(zumindest mein Compiler optimiert die insgesamt 252 Bytes großen aber
unbenutzten Variablen weg)
- Zeichenfolgen in main():
72 Bytes
- Stack für FAT-Aufrufe:
schätzungsweise ca. 60 Bytes
Insgesamt sind das knapp 940 Bytes. Dein Controller hat 2 kBytes, es
sollte also nicht zu Problemen kommen. Dennoch könntest Du mal
versuchen, mit den folgenden Änderungen Speicher zu sparen:
- Dateien nur mit einem Buchstaben benennen.
- Für das Öffnen des Wurzelverzeichnisses und das Anlegen der Dateien
den selben dir_entry verwenden (fat16_open_dir() macht intern eine
Kopie, die im Handle abgelegt wird).
- Die unbenutzten Variablen buffer und fd zur Sicherheit entfernen.
Mein Testprogramm findest Du angehängt. Zur Laufzeit gibt es hier
folgendes aus:
1
manuf: 0x06
2
oem: RK
3
prod: SD
4
rev: 00
5
serial: 0x000004b1
6
date: 12/5
7
size: 127139840
8
copy: 0
9
wr.pr.: 0/0
10
format: 0
11
free: 126644224/126693376
12
1: success1
13
2: success2
14
3: success3
15
4: success4
16
5: success5
17
6: success6
18
7: success7
19
8: success8
20
9: success9
Linux zeigt dann an:
1
drwxr-xr-x 2 root root 16K 1970-01-01 01:00 ./
2
drwxr-xr-x 24 root root 4,0K 2007-10-15 09:04 ../
3
-rwxr-xr-x 1 root root 0 1980-01-01 01:00 1*
4
-rwxr-xr-x 1 root root 0 1980-01-01 01:00 2*
5
-rwxr-xr-x 1 root root 0 1980-01-01 01:00 3*
6
-rwxr-xr-x 1 root root 0 1980-01-01 01:00 4*
7
-rwxr-xr-x 1 root root 0 1980-01-01 01:00 5*
8
-rwxr-xr-x 1 root root 0 1980-01-01 01:00 6*
9
-rwxr-xr-x 1 root root 0 1980-01-01 01:00 7*
10
-rwxr-xr-x 1 root root 0 1980-01-01 01:00 8*
11
-rwxr-xr-x 1 root root 0 1980-01-01 01:00 9*
Falls Du Dich mit der Struktur der Verzeichniseinträge einigermaßen
auskennst, die sehen dann korrekt z.B. so aus:
Beim Debuggen ist mir zwar noch etwas anderes aufgefallen, dies betrifft
jedoch nur das Auslesen von (sehr großen) Verzeichnissen und hat nichts
mit Deinen Problemen zu tun. Wahrscheinlich gebe ich dazu dann später
eine neue Release raus.
Viele Grüße,
Roland
Guten Tag zusammen
Ich möchte für ein späteres Projekt (GPS-Logger) ein SD Karte Testmässig
ansteuern.
Nun habe ich mit einem Atmega48 die Testschaltung aufgebaut. Die
Speisung der SD Karte erfolgt über einen 3.3V Spannungsregler. Die
Pegelanpassung der Datenleitungen erfolgt über Spannungsteiler.
Die SD Karte ist eine Panasonic 256MB.
Der Grund warum ich hier schreibe ist, dass ich bis jetzt das
Initialisieren der Karte noch nicht hinbekommen habe. Ich hoffe ihr
könnt mir irgendwelche Tipps geben welche ich noch zu beachten habe.
Falls ihr noch Infos bezüglich der Hardware oder sonstigem braucht werde
ich das natürlich nachliefen. Mir fällt momentan nichts relevantes mehr
ein.
Die Software habe ich soweit anpassen müssen das sie in den Atmega48
passt, das heisst es ist nur noch fast das Init mit fast allen
benötigten Funktionen vorhanden. sd_raw_read() konnte ich aufgrund des
Platzmangels nicht mehr implementieren.
Aufgrund des Platzproblems stelle ich noch eine weiter Frage. Ist es
normal das die Programme so gross sind?
Programmgrösse ohne FAT Unterstützung : ca 9kb
Programmgrösse mit FAT Unterstützung: ca 40kb
Ich danke euch schon jetzt für eure Mühe.
Gruss
Hallo Roland,
hast Du bei Deinem Test das Original-SPI oder das USART im SPI-Modus
benützt? Ich habe vorhin meinen Kartensockel auf das Original-SPI
umgelötet, und damit funktionert alles; ich kann die Dateien anlegen,
eine öffnen und etwas einschreiben, die Datei wird dabei automatisch
vergößert.
Das Ergebnis sieht folgendermaßen aus:
Hallo Martin,
Schön zu hören, dass Du es zumindest mit dem normalen SPI am Laufen
hast. Meine Tests waren wie immer auch mit der normalen Schnittstelle,
meine Platine sieht gar nichts anderes vor.
Habe mir in Deinem Code auch die Initialisierung sowie das Senden und
Empfangen über den USART-SPI angeschaut, es ist mir aber nichts
aufgefallen.
Vielleicht hat es etwas mit der zusätzlichen Pufferung im Vergleich zum
normalen SPI zu tun (s. Datenblatt Kap. 19.7)? Oder es gibt ein
Timing-Problem mit dem Chip-Select? Naja, das ist eher unwahrscheinlich.
Viele Grüße,
Roland
@stucmath
Was machst Du mit einer SD-Kartenunterstützung, in der Du sd_raw_read()
weglässt?!?
Deine Codegrößen sind nicht normal, Du solltest einmal die Einstellungen
Deines Compilers überprüfen und dort eine Größenoptimierung einstellen.
Aber selbst mit der Größenoptimierung wirst Du auf dem ATmega48 nicht
glücklich. Meine Beispielanwendung braucht für Nur-Lese-Unterstützung
mindestens einen mega8/88, mit Schreibunterstützung einen mega16/168.
Gruß,
Roland
Na ja das bringt eigentlich wirklich nichts. Aber ich wollte nur für
denn anfang erreichen das ich die SD Karte Initialisieren kann. Das
sollte doch auch ohne sd_raw_read() klappen?
Ich kompiliere meine Projekte immer über eine build.bat Datei. Die
Optimierung habe ich auf -Os gestellt. Sollte doch eigentlich in Ordnung
sein.
Mit Lese- Schreibunterstützung meinst du mit oder ohne FAT?
Ich werde mir also am besten einmal ein Testboard mit einem Atgema32
aufbauen.
Danke für deine Hilfe
Gruss
Ja klar, für die Initialisierung selbst brauchst Du nur sd_raw_init().
Die Optimierung ist so auch in Ordnung.
Wo liest Du denn Deine Codegrößen ab? Doch nicht an der Größe der
Ausgabe des Linkers? Benutze (am Beispiel des sd-readers)
avr-size -A sd-reader.out
In der Ausgabe entspricht der Flash dem Segment .text und das statisch
allokierte RAM wird in die Segmente .data und .bss ausgegeben.
Die Angabe der Controllergrößen bezog sich auf meine Anwendung, also mit
FAT-Unterstützung und der Mini-Shell über UART.
Gruß,
Roland
Hallo Roland,
RTFM kann ich da nur sagen! Deine Vermutung, es könnte mit der
zusätzlichen Pufferung beim USART-SPI zu tun haben, war goldrichtig.
Meine Sendefunktion sah so aus:
1
void sd_raw_send_byte(uint8_t b)
2
{
3
while ( !(UCSR0A & (1<<UDRE0)) );
4
UDR0 = b;
5
}
Dies scheint zunächst richtig zu sein, hat aber tatsächlich einen
gravierenden Fehler. Da mit dem Sendebyte auch ein Byte empfangen wird,
bleibt bzw. wird das UDRE0-Bit gelöscht, und beim nächsten
Funktionsaufruf bleibt das Programm in der while-Schleife hängen. Um
dieses Bit zu setzen, muß ich das Empfangsbyte lesen.
Das habe ich nun ergänzt:
1
void sd_raw_send_byte(uint8_t b)
2
{
3
while ( !(UCSR0A & (1<<UDRE0)) );
4
UDR0 = b;
5
while ( !(UCSR0A & (1<<RXC0)) );
6
b = UDR0;
7
}
Mit diesen zwei zusätzlichen Zeilen läuft jetzt alles einwandfrei!
Herzlichen Dank für Deine Unterstützung und viele Grüße!
Martin
Hmm da habe ich doch wieder einmal etwas gelernt. Habe die .hex grösse
direkt am file gelesen. Mit avr-size -A sd_reader.hex zeigt es mir 14470
byte an also 14.1kbyte. Ich denke so ist alles in Ordnung. Danke für den
Tipp.
Habe nun auf einen Atmega32 umgestellt. Leider funktioniert das Init
dort auch nicht. Die Serielle Schnittstelle meldet nur:
MMC/SD initialization failed
Ich gehe mal schwer davon aus das dies ein Hardware Fehler sein wird.
Aber was könnte das sein? Wie schon gesagt für die Speisung verwende ich
einen Spannungsregler (3.3V). Als Pegelwandler sind Widerstände
zuständig. Diese könnten durch die Toleranzen so zwischen 3.0 - 3.2V
liegen.
Nun da ich keine noch keine Erfahrung mit SD-Karten habe frage ich hier
wo könnten denn Fehler aufgetaucht sein? Ich hoffe du (ihr) könnt mir
weiterhin hilfreiche Tipps geben.
Gruss
Hallo,
mir geht es da ähnlich. Anbindung der MMC ist nach dem einfachen Schema
von Ullrich Radig erfolgt. Am Oszi sehe ich das sich auf CS, DI und CLK
etwas tut. Auf DO ist aber schweigen. VCC der Karte liegt bei 3.29V. Das
gleiche Verhalten habe ich mit zwei Karten (1GB Kingston, 2GB no-name).
Softwareseitig geht dann natürlich das reset Kommando schief, da dies
einen definierten Rückgabewert von der Karte erwartet.
Tipps wären hochwillkommen.
Gruß
Malte
@Malte, stucmath
Hmm, mehr als auf meinen Schaltplan zu verweisen kann ich leider nicht.
Der funktioniert bei mir ohne Probleme.
Die Dioden-Lösung ist allerdings nicht optimal. Bei Zugriffen auf die
Karte sackt die Versorgungsspannung durch den Stromfluss von ca. 3,7
Volt auf Werte um die 3,3 Volt ab. Mag sein, dass das die ein oder
andere Karte stört, meine laufen glücklicherweise problemlos.
Gruß,
Roland
Hallo Roland und Malte
Bei mir funktioniert es mittlerweile. Der Fehler war das ich aus mir
unbekannten Gründen (Dummheit) die MISO Leitung auch über einen
Spannungsteiler geschalten habe.
@Roland
Ich danke dir vielmals für deine Hilfe und auch für die Software. Die
ist einfach nur Klasse.
@Malte
Roland hatte hier einmal geschrieben das wenn man mit einem
Spannungsregler arbeitet muss darauf geachtet werden, dass die ein wenig
unter den 3.3V liegen. Deshalb habe ich meinen Spannungsteiler
folgendermassen gewählt:
3.3K
2K
Ergibt dann etwa eine Spannung von 3.1V
Gruss
Malte
Das tut ja richtig weh Dich leiden zu sehen. ;)
Nur so ein paar Tips:
Der LM317 ist ca. 20 Jahre alt und eher ungeeignet um 3.3V für eine
SD-Karte bereit zu stellen weil er ständig eine Mindestlast von einigen
mA zum funktionieren benötigt. Wenn Du das sicher stellen kannst ist das
o.k. - sonst aber kein Beitrag zum Thema Energie sparen. Es gibt
modernere IC's dafür.
Du kannst an jeder beliebigen Stelle in Roland's SD-Reader ein paar
zusätzliche printf's einbauen um zu beobachten an welcher Stelle es
genau hakt. Diese kannst Du Dir ganz in Ruhe via Hyperterminal etc. am
PC angucken.
Besonders spannend sind die Sachen die in "sd_raw.c" in "sd_raw_init()"
passieren. Guck Dir genau an ob Du auch einen Karten-Slot hast der
Kontakte für configure_pin_available() (=SD-Card eingesteckt) und
configure_pin_locked() (=SD-Card schreibgeschützt) bereitstellt.
Wenn das nicht der Fall ist muß der Original-Code angepaßt werden!
Viel Glück,
Torsten
Hallo,
nach ich mit einer "billigen" SD-Karte von Reichelt Probleme hatte, hab
ich's jetzt mit einer etwas teureren Karte vom Conrad fast hinbekommen.
Ich habe die letzte Version von Roland auf einem ATMega168 laufen,
einzige Änderung zum Orginal Source Code ist, dass ich die Abfragen
locked und available folgendermassen geändert habe:
in sd_raw_config.h
Jetzt zu meinem Problem: alle Shell Befehle funktionieren, bis auf cat
<file> und write <file> <offset>, beim Aufruf dieser Funktionen hängt
das Programm sich auf oder kommt mit der Initialisierung wie nach einem
Reset zurück.
Kennt jemand das Problem ?
Gruss Reinhard
Servus Reinhard,
Wie Martin schon korrekt ausgeführt hat, musst Du das #define auf 1
ändern, sonst nimmt meine Software an, dass der Schreibschutz aktiviert
ist. Das liegt daran, dass in meiner Schaltung die Port-Pins gegen Masse
geschaltet werden, wenn der Schutz aktiv ist.
(Der Schreibschutz bei den MMC/SD-Karten ist allein durch die Software
realisiert. Der Schalter an der Karte ist nur ein Kunststoffnippel, von
dem der Kartencontroller nichts weiß. Erst die Host-Software kann über
einen Schalter im Sockel die Position des Schreibschutzschalters
feststellen und verweigert gegebenenfalls den Schreibzugriff.)
Viele Grüße,
Roland
Hallo Martin, hallo Roland
ich habe eure vorgeschlagene Änderung durchgeführt. Das führt jetzt zu
einer "sauberen" Programmierung, wenn die Schalter für Locked und
Available fehlen, beseitigt aber nicht das beschriebene Problem mit
"cat" und "write". Schreiben konnte ich ja auch schon vorher, "touch",
"rm" und "mkdir" als Shell Befehle funktionieren ja.
Hier mal ein Abdruck des Terminals:
1
> manuf: 0x1b
2
oem: SM
3
prod: SMI
4
rev: 10
5
serial: 0x099da84f
6
date: 7/7
7
size: 1017643008
8
copy: 0
9
wr.pr.: 0/0
10
format: 0
11
free: 1016758272/1017249792
12
> ls
13
abc/ 0
14
file.txt 16
15
a/ 0
16
>
17
> cat file.txt
ab hier hängt's. Ein weiteres Beispiel, wenn der File in einem
Unterverzeichnis ist:
1
manuf: 0x1b
2
oem: SM
3
prod: SMI
4
rev: 10
5
serial: 0x099da84f
6
date: 7/7
7
size: 1017643008
8
copy: 0
9
wr.pr.: 0/0
10
format: 0
11
free: 1016758272/1017249792
12
> cd abc
13
>
14
> ls
15
./ 0
16
../ 0
17
abc.txt 24
18
>
19
> cat abc.txt
20
manuf: 0x1b
21
oem: SM
22
prod: SMI
23
rev: 10
24
serial: 0x099da84f
25
date: 7/7
26
size: 1017643008
27
copy: 0
28
wr.pr.: 0/0
29
format: 0
30
free: 1016758272/1017249792
31
>
Hier springt das Programm an den Anfang.
Ich hoffe, dass der Fehler jetzt klarer beschrieben ist und ihr helfen
könnt.
Gruss Reinhard
Hallo Reinhard,
Nachdem Du (bis auf die zwei besprochenen Änderungen) genau den gleichen
Code benutzt wie ich und auch den gleichen Controller, tippe ich jetzt
einfach mal auf die Hardware. Könntest Du diesen bitte schildern oder
einen Schaltplan posten? Interessant ist insbesondere die Anbindung der
Karte an den Controller und die Stromversorgung.
Falls das alles unverdächtig ist, könntest Du vielleicht auch bitte ein
Karten-Image erstellen und mir zuschicken. Eventuell finde ich am
Donnerstag Zeit, um mal wieder eine Debugging-Sitzung einzulegen...
Gruß,
Roland
Hallo Roland,
erst mal Danke für deine super-schnelle Reaktion.
Zu meiner HW: ich benutze das Development Board von myavr.de, allerdings
abweichend von der Ursprungsversion mit einem ATMega168. Schaltplan dazu
unter http://myavr.de/download/techb_myavr_board_lpt.pdf. Getaktet wird
das Board mit 3,6864 MHz. Eine Besonderheit ist vielleicht, dass das
Board aufgrund des 6V Spannungsreglers und der Reihendiode mit ca. 5,3V
betrieben wird. Die SD-Karte ist wie in deinem Schaltplan mit
Spannungsteiler (3,3k gegen Masse, 1,8k in Reihe) an die Datenports
angebunden. DATA OUT direkt an MISO. Die SD-Karte wird mit einem LM317
mit 3,3V versorgt. Da der Spannungsteiler die Datenports geringfügig
über 3,3V zieht, habe ich auch mit einer Versorgungsspannung von 3,5V
probiert, was aber keine Veränderung zeigte. Die SD-Karte ist eine 1GB
von Transcend, gleiches Verhalten aber auch bei einer 2GB Karte.
Ich denke eher, dass der Fehler in der SW zu suchen ist. Ich habe
zumindest den Fehler durch Debug-Ausgaben auf dem Terminal soweit
eingrenzen können, dass sich dass Programm bei Eingabe von "cat <file>"
in folgender IF Abfrage aufhängt (Funktion: uint8_t
fat16_read_root_dir_entry(const struct fat16_fs_struct* fs, uint16_t
entry_num, struct fat16_dir_entry_struct* dir_entry)) - ca. Zeile 398
in fat16.c
Leider hören da meine C-Kenntnisse bei der Fehlersuche auf. Aber
vielleicht hilft dir das ja, den Fehler einzugrenzen.
Wenn du glaubst mit einem Karten-Image weiterzukommen, schick ich dir
das gerne zu, kommt dann separat per Mail.
Ich danke dir nochmals für deine freundliche Hilfe
Gruss Reinhard
Hallo Reinhard,
Die Variable device_read_interval ist ein Funktionspointer auf
sd_raw_read_interval(), welche wiederum sd_raw_read() mehrfach aufruft.
Wenn er also in der von Dir zitierten if-Abfrage hängen bleibt, müsstest
Du in den genannten Funktionen in sd_raw.c weiterforschen.
An dieser Stelle können durchaus Hardware-Probleme eine Rolle spielen,
etwa wenn die Karte nicht korrekt antwortet. Wenn ich Dein Karten-Image
habe, werde ich dieses auf meine Karte schreiben und sehen, ob
vielleicht bestimmte Parameter des Dateisystems meinem Code
Schwierigkeiten machen.
Gruß,
Roland
Hallo Roland & Rest,
ich habe vor eine Micro SD Karte auf meiner neuen Propellerclock (50 RGB
LEDs) mitdrehen zu lassen.
Erst dachte ich an externes flash rom, auf das die Bilder beim
Bootvorgang zwischengespeichert werden, jetzt ist es mir aber gelungen
die CPU Last auf unter 30% für die Ansteuerung der LED Treiber zu
reduzieren und ich denke drüber nach den Flash Rom komplett wegzulassen.
Die Sache ist nur, dass ich jede Sekunde 687kByte brauche und das Holen
dieser Daten am Besten innerhalb von 50% CPU Last bewältigen möchte.
Unterm Strich komme ich auf eine benötigte Lesegeschwindigkeit von knapp
1,4 MByte/s
Meine Frage an euch wäre jetzt ob das mit dem Code überhaupt möglich
ist. SPI Frequenz wäre 8MHz, als Controller hatte ich wegen der
benötigten I/Os eigentlich den mega128 eingeplant, vielleicht ginge
jetzt ja auch ein mega32?
Gruß
Kai
habe gerade nochmal den Taschenrechner bemüht und dabei ist mir
aufgefallen, dass eine 8MHz Taktfrequenz dafür gar nicht ausreichen
würde...
Habe also ein wenig umstrukturiert, brauche jetzt auch etwas über 30%
CPU, komme aber "nur" noch auf 430kByte in einer Sekunde, bei 50% CPU
wären das dann 860kByte/s oder 6880kBit/s, was mit 8MHz SPI schaffbar
wäre.
Wo es der AVR jetzt schafft, geht das dann auch mit dem Programm oder
wird zuviel Rechenzeit für den Empfang/Pufferung verbraten?
Hallo Kai,
Aufgrund meiner Erfahrungen denke ich nicht, dass Du das hinbekommen
wirst. Zumindest nicht mit FAT und ohne viel(!) Pufferspeicher, den Du
Dir ja eigentlich sparen wolltest.
Wenn Du die Karte ohne Dateisystem benutzt, und ein Interrupt-basiertes
Lesen der SD-Karte implementierst, könnte es vielleicht gehen. Doch
selbst dann ist Dein Vorhaben sehr knapp am Limit der maximalen
ISP-Frequenz. Die Ansteuerung der Karte benötigt viele Wartezyklen und
die Übertragung vieler Dummy-Bytes, die die Netto-Datenrate weit unter
das theoretische SPI-Limit drücken. Von dem Overhead eines Dateisystems
ganz zu schweigen...
Du müsstest also Deine Anforderungen an die Datenrate noch erheblich
drücken...
Viele Grüße,
Roland
Hi Roland,
das ist aber doof :(
weiter drücken geht leider nicht ohne die Bildwiederholfrequenz
(momentan 20/s) zu senken.
Was ich mir vorstellen könnte wäre die Frequenz auf 10 Bilder/s zu
drücken und damit einen Faktor 2 rauszuholen. Dann würde ich ein Bild
eben zweimal anzeigen... allerdings brauche ich dann auch einen Puffer,
in den ein ganzes Bild reinpasst, welches aber 43kByte groß ist...
Da ich sowieso schon länger vorhabe eine SD Karte anzusteuern und die
Sockel auch schon länger habe, bin ich gerade dabei eine Schaltung auf
Lochraster aufzubauen (ja, mein Sockel passt auf Lochraster).
Als µC benutze ich einen mega8.
Da ich aber ein fauler Codevision User bin, werde ich deinen Code wohl
in Codevision übersetzen müssen :(
Werde hoffentlich nicht der einzige sein, der davon profitiert^^
Gruß
Kai
@ Reinhard
Habe jetzt mal Dein Image auf meine Karte gespielt:
1
manuf: 0x06
2
oem: RK
3
prod: SD
4
rev: 00
5
serial: 0x000004b1
6
date: 12/5
7
size: 127139840
8
copy: 0
9
wr.pr.: 0/0
10
format: 0
11
free: 1016758272/1017249792
12
> ls
13
abc/ 0
14
file.txt 16
15
a/ 0
16
> cat file.txt
17
00000000: 61 62 63 64 65 66 67 0a
18
00000008: 31 32 33 34 35 36 37 0a
19
> cd abc
20
> ls
21
./ 0
22
../ 0
23
abc.txt 24
24
> cat abc.txt
25
00000000: 31 32 33 34 35 36 37 38
26
00000008: 39 30 0a 61 62 63 64 65
27
00000010: 66 67 68 69 6a 0a 20 0a
Es funktioniert also prinzipiell. Ich hatte aber hin und wieder Probleme
mit dem Wechsel in das Verzeichnis. Nach ein bisschen Debugging denke
ich, dass dieses Problem, genauso wie Deines, an der Speicherknappheit
liegt. Ich würde Dir empfehlen, meine Mini-Shell einfach mal durch ein
kleines Demo-Programm zu ersetzen, welches wirklich nichts anderes
macht, als eine Datei anzulegen, in sie zu schreiben und wieder zu
schließen. Das sollte dann funktionieren.
Gruß,
Roland
Hallo Roland,
habe deinen Vorschlag befolgt und aus main.c alles aus der Minishell
gelöscht bis auf "cat", "sync" und "write". Nur mit diesen Befehlen
funktionierts, wie das Beispiel zeigt:
1
manuf:0x1b
2
oem:SM
3
prod:SMI
4
rev:10
5
serial:0x099da84f
6
date:7/7
7
size:1017643008
8
copy:0
9
wr.pr.:0/0
10
format:0
11
free:1016709120/1017249792
12
>cat2.txt
13
00000000:200a020000000000
14
>write2.txt0
15
<jetztfunkt's
16
<dankeanRoland
17
<
18
>cat2.txt
19
00000000:6a65747a74206675
20
00000008:6e6b74277364616e
21
00000010:6b6520616e20526f
22
00000018:6c616e646e20526f
23
>
Sobald ich einen weiteren Shell Befehl, egal ob "ls" oder "touch"
zusätzlich rein nehme, hängt sich das Prog wieder auf. Vielleicht liegts
wirklich an der Grösse des Programms und dem Füllgrad des Flash obwohl
AVR Studio nur 13.812 Byte und 84,3% meldet. Im Moment komm ich hier
nicht weiter.
Werd mich mal dran machen, Werte aus dem A/D Wandler in eine Datei zu
schreiben, mal sehen, ob das klappt.
Gruss Reinhard
>Sobald ich einen weiteren Shell Befehl, egal ob "ls" oder "touch">zusätzlich rein nehme, hängt sich das Prog wieder auf. Vielleicht liegts>wirklich an der Grösse des Programms und dem Füllgrad des Flash obwohl>AVR Studio nur 13.812 Byte und 84,3% meldet. Im Moment komm ich hier
Jungs, nehmt doch einfach einen ATMega32. Nicht das Flash
ist am Ende, es ist das RAM !
Hallo Reinhard,
Wie Holger schon angemerkt hat, geht es nicht ums Flash, da sind ja noch
ein paar Kilobyte frei. Das RAM ist komplett belegt, und sobald der
Stack in den Heap bzw. in den statisch allokierten Bereich reinwächst,
gibt es Probleme. Dann kann alles passieren, vom merkwürdigen Verhalten
bis zum Absturz.
Zum Testen mag Dein Controller reichen, für die eigentliche Anwendung
wirst Du aber ein Modell mit mehr RAM brauchen.
Gruß,
Roland
holger wrote:
> Jungs, nehmt doch einfach einen ATMega32. Nicht das Flash> ist am Ende, es ist das RAM !
Wohl wahr, das ist der wunde Punkt.
2k SRAM reichen zwar für Roland's Beispiel mit dem SD-Reader, für mehr
aber nicht. Programmiert man eigene Sachen dazu erlebt man die gleichen
merkwürdigen Effekte. Erst mit einem ATmega644 (4k SRAM) lief alles in
meinem Fall so wie es sein sollte.
Torsten
Hallo,
gibt's denn keine Möglichkeit das zu kontrollieren - entweder beim
Compilieren/Linken vorher oder zur Laufzeit ?
(btw. - der ATMega168 hat nur 1k !)
Gruss
Reinhard
Hallo Reinhard!
Nein, das geht in der Regel nicht, dazu wäre eine Laufzeitanalyse
notwendig. Nur wenn das statisch allokierte RAM (also die Gesamtgröße
aller globalen Variablen) bereits zu groß ist, kann das der Linker
feststellen. Das hilft aber nichts, weil das RAM meist schon vorher
durch den Stack (also lokale Variablen und die Parameter bei
Funktionsaufrufen) und den Heap (sprich malloc()/free()) aufgebraucht
wird.
Ja, der mega168 hat nur 1kB, deshalb ist er ja so sehr am Limit.
Gruß,
Roland
Hallo zusammen
Hat jemand schon mit Roland Riegel's SD/MMC Software eine Micro SD Karte
angesteuert?
Versuche dies nämlich gerade. Die Initialisierung ist wahrscheinlich
erfolgreich (muss ich noch genau untersuchen) aber es werden dann keine
Disk Infos angezeigt.
Gruss
Hi Matthias,
Ja, ich habe bei meiner Entwicklung sowohl Micro-SD (über Adapter) als
auch normale SD-Karten benutzt.
Eigentlich sollte es auch keine Unterschied, mal abgesehen von den
üblichen Inkompatibilitäten, geben. Eine Micro-SD ist eine normale SD -
halt nur kleiner.
Gruß,
Kai
Wunderbar dann sollte das also klappen. Dann habe ich wieder einmal ein
Fehler in meiner Schaltung :-)
Danke für deine Hilfe dann werde ich noch ein bisschen weiter probieren.
Gruss und schönes Wochenende
@Roland Riegel,
feine Sache, habe ATmega8L mit Miniversion ohne Probleme zum laufen
gebracht. Jetzt bestehen ja richtige Möglichkeiten durch diese Software.
Besten Dank
Udo
Hallo,
Das sieht ja Prima aus. Moecht ich gerne auch ausprobieren!
Könnte freundlicherweise jemand einen link zur Miniversion
fuer Atmega8L posten.
Irgendwie ist der Thread bezueglich Uebersichtlichkeit an
seine Grenzen gestossen :)
danke
Gast
@Udo, Gast
Bitte beachtet bitte, das in der allerersten Version diverse Fehler
enthalten sind, die in dem neuesten Release behoben sind. Für möglichst
kleinen Code also bitte nicht veraltete Ausgaben nutzen, sondern die
jeweils neueste entsprechend abspecken. In den letzten fast zwei Jahren
hat sich schließlich einiges getan...
Gruß,
Roland
@Gast,
als Anhang das Programm für ATmega8L.
@R. Riegel,
es ging aber um den Link und nicht um die Versionen. Zum Hardwareaufbau
hat bestimmt jeder so seine eigenen Vorstellungen, ich finde es
einfacher gleich alles mit 3,3V zu betreiben deswegen der ATmega8L,
andere haben vielleicht schon Hardware mit 5V und wollen dann aber diese
SD-Karten betreiben.
Die letzte Version der Software steht doch bestimmt auf Deiner Webseite,
habe jetzt aber auch nicht da nachgeschaut, gehe aber davon aus dass so
etwas selbstverständlich ist.
Dann finde ich es sehr wichtig so viel zu Lesen wie es geht um auch
selbst zu entscheiden ob dass so alles stimmt wie es gerade beschrieben
wird, wer weiß schon alles. Dann sind die eigenen Fehler sowieso die
schlimmsten und dass geht nur mit Ausdauer am Projekt.
Wie soll ich dass alles beschreiben?
Udo
Hi,
ich bin endlich dazu gekommen an meiner Cocktailmaschine zu werkeln. Ich
habe bereits ein rudimentäres Programm mit 3 Tastern, LCD-Display zur
Auswahl auf Basis eines Atmega16 am laufen. 2 komplette 8 Bit Ports
wollte ich wohl für die Pumpen bzw. Magnetventile reservieren. Leider
reicht mir der EEPROM zum speichern von Rezepten nicht aus, da bekomm
ich maximal 20 Rezepte untergebracht weil ich speichere die Namen der
Cocktails als Strings mit maximal 18 Zeichen für das 4*20 LCD. Zur Zeit
nutze ich den Programmspeicher dafür, was ich aber sehr unfexibel finde.
Ich ich will nicht bei jeder Änderung den Chip neu programmieren und da
bin ich über diesen Beitrag gestolpert.
Ich finde die Idee mit der SD Karte recht gut, weil dann kann ich die
Rezepte am PC zusammenfriemeln und darauf speichern, der Atmega muss sie
dann nur lesen können. Jedoch benötige ich nich wirklich ein Dateisystem
wie FAT16 ... ich bräuchte auch nur eine Datei mit meinem eigenem
Datenformat. Ich würde dann also nur die SW_RAW routinen verwenden und
quasi mein eigenes Dateisystem, d.h. einfach nur ein datenstream in
einem bestimmtem Format darauf speichern und auf dem PC ein Programm
schreiben welches die Daten auf der SD karte in diesem Format speichert.
Soweit so gut. Grad mal geguckt es gibt ja fasst nur noch Karten die
mindestens 1GB Speicherkapazität haben, soviel brauche ich nun auch
wieder nicht, mir würde sogar 1MB dicke reichen. Jetzt wollte ich mal
fragen ob es da nicht eine bessere Lösung gibt. Außerdem meine ich hier
gelesen zu haben, dass man die Daten nur in 512byte Blöcken lesen kann,
heißt das jetzt das ich immer mindestens 512byte in einem rutsch lesen
muss?
Danke im Vorraus.
Hallo Jan,
Ob du SD-Karten nutzt oder nicht, musst letzten Endes Du entscheiden.
Beachte allerdings, dass der Hardwareaufwand relativ gering ist und der
Speicher pro MB unschlagbar billig, verglichen mit externen EEPROMs oder
Flash-Chips.
In der Regel werden die SD-Karten 512-Byte-weise angesprochen, ja. Wenn
Du meine sd_raw-Routinen verwendest, ist das aber wurscht, da diese
einen wahlfreien Zugriff mit beliebiger Blockgröße ermöglichen.
Gruß,
Roland
PS: Wenn Du die Strings mit dynamischer Länge ablegst und mit einem
Null-Byte abschließt, kannst Du auch ein bisschen Platz sparen.
Hallo,
ich habe meine Schaltung jetzt auch ans laufen bekommen, ein kleines
Verstänissprob. bleibt. Wenn ich mit
...
uint8_t buffer[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08};
fat16_write_file(fd, buffer, 9);
...
fat16_close_file(fd);
...
Auf die Karte schreibe werden 2 Byte und nicht 9 geschrieben. Rufe ich
vorher:
fat16_resize_file(fd, 9);
auf passt es.
Ist das ein zu erwartendes Verhalten?
An dieser Stelle auch mal ein herzliches Dankeschön an Roland für die
klasse lib.
Gruß
Malte
Hallo Roland,
ich gebe die anzahl der geschriebenen Bytes auf dem Display aus. Das
passt soweit. Ich dachte sd_raw_sync() ist nicht erforderlich wenn ich
die Datei mit vor dem Entfernen mit fat16_close_file(...) schliesse.
Dann hatte ich gestern aber noch weitere seltsame Effekte. Bin jetzt
aber nicht ganau in der lage diese richtig zu beschreiben.
Ich denke ich schau mal ob da nicht der Stack zu gross wird.
Gruß
Malte
Hallo Malte,
Doch, in den bisherigen sd-reader-Versionen ist der Aufruf von
sd_raw_sync() immer manuell auszuführen. Am besten beispielsweise vor
längeren Zugriffspausen, wenn die Wahrscheinlichkeit hoch ist, dass die
Karte abgezogen wird.
Ich hatte auch schon dran gedacht, sd_raw_sync() beim Aufruf einiger
FAT-Funktionen automatisch auszuführen. Vielleicht werde ich das mal
implementieren. Wenngleich das in einigen Zugriffsszenarien den
Puffereffekt zumindest teilweise zunichte machen könnte...
Nebenbei bemerkt glaube ich nicht, dass sd_raw_sync() bei Dir das
Problem ist, da die ersten zwei Bytes ja geschrieben werden. Die
restlichen sieben sollten dann ja gleichzeitig in dem gleichen Sektor
landen.
Zu Deinem Fehlerbild fällt mir im Moment außer dem von Dir erwähnten
RAM-Mangel auch nichts passendes ein. Welchen AVR nutzt Du eigentlich?
Gruß,
Roland
Hi Roland,
ich verwende einen ATMEGA128. Der ist allerdings mit knapp 3500 bytes
sram recht gut gefüllt. Stack muss dann noch in die verbleibenen 500
bytes passen.
Dynamischen Speicher über malloc oder die builtin Funktionen verwende
ich nicht. Am Anfang der oben angehängten Routine habe ich noch 187
bytes Speicher frei.
Mit sd_raw_sync() scheint es jetzt soweit zu funktionieren. Danke
Gruß
Malte
Hi,
as I see there is a lot of expertise (which I am lacking) in this forum
I would kindly ask you whether it would be possible to write a simple
"user fiendly library" based on Roland's code which is easy to use by
beginners as well - e.g.:
sd_init()
sd_open(&filename)(if it does not exist than create)
sd_date(&filename,year,day,..min,sec) (time stamp)
sd_write(&filename,*buffer)
sd_read(&filename,*buffer)
sd_append(&filename,*buffer)
sd_delete(&filename)
sd_close(&filaname)...
...
where buffer is a string[40] etc., so you printf(string,"%u...",temp).
filename is a string ( e.g. "\temp\new\measure1.txt")
So one can easily open a file and write data there.
I would say it is a half hour work for an expert to make this great
fat16 library available for an "standard" user who wants just write
temperature or some data into files..
pito
@pito,
I will not provide you with code, because all you need is more or less
already available with the main.c example application from the sd-reader
source. You just have to write up some wrapper functions into which you
put the example code:
sd_init: sd_raw_init(), partition_open(), fat16_open()
sd_open: fat16_get_dir_entry_of_path(), fat16_open_file()
sd_date: fat16_get_file_modification_date/time()
sd_write: fat16_write_file()
sd_read: fat16_read_file()
sd_append: fat16_seek_file(), fat16_write_file()
sd_close: fat16_close_file()
sd_delete: fat16_delete_file()
That would be it. You might also want to look at the mega-eth project
(http://www.roland-riegel.de/mega-eth/), where I reused the sd-reader
code and wrote something which equals your sd_init().
Greetings,
Roland
Hallo,
ich bin seit einiger Zeit dabei Daten auf einer Speicherkarte abzulegen.
Meine ersten Versuche liefen ohne FAT Dateisystem und nur mit
ansteuerung der Sektoren. Ich habe dafür das Beispiel von Ulrich Radig
genutzt.
Ich konnte damit ohne Probleme speichern.
Nun wollte ich jedoch etwas mehr probieren und mal das FAT16 System von
Roland Riegel testen.
Jedoch hab ich da so ein paar Probleme.
Ich nutze das Pollin-Board mit einem ATmega32 (mit internem Takt [8MHz])
und die Speicherkartenansteuerung ist eine Komplettlösung der Firma
E-LAB.
Des Weiteren nutze ich MMC-Speicherkarten, weil in den Slot keine
SD-Karten passen.
Es treten schon Probleme auf, wenn die "Fabrikdaten" ausgelsen werden.
Beim letzten Punkt, wo der freie und belegte Speicherplatz angezeigt
werden soll, hängt sich das Programm auf und es geht nicht weiter.
Kommentiere ich diese Zeile aus, läuft es erstmal.
Ich kann auch ohne Porbleme den Inhalt mit dem Befehl "ls" auslesen.
Jedoch kann ich keine neuen Dateien erstellen oder in vorhandene
Textdateien hineinschreiben.
Ich wollte das ganze System als eine Art Datenlogger nutzen.
Was mir auch noch aufgefallen ist, das manche Karten gar nicht erst
erkannt werden.
Ich hoffe ihr könnt mir bei diesem Problem weiter helfen.
gruß
Thomas
Roland Riegel wrote:
..
> (http://www.roland-riegel.de/mega-eth/
Wow. Gratuliere zum neuen Projekt! Sieht sehr gut aus.
BTW: Hast es hier ja garnicht vorgestellt.. ;)
Torsten
Guten Morgen,
ich hab gestern noch ziemlich lange probiert das Problem zu finden. Hab
noch mehr Speicherkarten getestet und sogar mal ne SD-Micro + Adapter
ausprobiert.
Irgendwie komme ich da nicht weiter.
Hab hier nochmal den Link von dem Speicherkartenmodul:
http://www.e-lab.de/components/cf_and_co.html
Es handelt sich dabei um das "MMC Card Interface for MINI-SD".
Das Pollinboard sollte, so denke ich, einigermaßen bekannt sein:
http://www.pollin.de/shop/shop.php
Am Quellcode kann es ja eigentlich nicht liegen. Und meine
Speicherkarten waren alle 128MB groß oder kleiner. Damit sollten also
auch keine Probleme entstehen.
Was mich am meisten wundert ist, dass bei den Karten, die funktionieren,
nur die Lesebefehle ohne Probleme klappen. Bei den Schreibbefehlen
bleibt er immer hängen.
Nutze zum Testen WindosXP mit Hyperterminal bzw. Hterm.
Vielleicht hat ja jemand schon so ein ähnliches Problem gehabt?!
gruß
Thomas
Hallo Thomas,
Mit den paar Angaben die Du machst kann man nur raten.
Überprüfe Deine Konfiguration in sd_raw_config.h. Finde auch mal selbst
heraus, wo genau er hängen bleibt. Füge vor und hinter jeden zu
untersuchenden Funktionsaufruf Debug-Ausgaben ein, ebenso in den
aufgerufenen Funktionen selbst. Versuche so einzukreisen, bis wo er
kommt.
Versuche doch erst mal den Sektorzugriff über sd_raw_read() und
sd_raw_write() zum Laufen zu bringen, erst dann solltest Du über FAT16
nachdenken.
Gruß,
Roland
@ Roland:
Also die Sende und Empfangsfunktionen ohne FAT16 funktionieren ohne
Probeme. Diese gingen ja auch schon, als ich das Projekt von Ulrich
Radig verwendet hatte.
Um zu überprüfen, wo er hängen bleibt, lass ich mir vor den Funktionen
immer Meldungen über die Uart ausgeben.
Und wie gesagt, er bleibt ja schon dann hängen, wenn er den freien
Speischerplatz angeben soll.
Aber ich werde jetzt erst einmal alle anderen, auch nicht genutzen
Funktionen überprüfen und nochmal testen, was passiert, wenn ich den
Code nur auf die Schreibfunktion begrenze.
Was mich aber mal noch interessiert, ist die Frage zu den
Speicherkarten. Sind da schon Probleme bekannt, dass es mit einigen
Typen Probleme gibt?
Ich habe sie ja alle unter Windows mit FAT formatiert.
gruß
Thomas
Hallo Thomas,
Selbst habe ich meinen Code nur mit SD-Karten ausprobiert, von anderen
habe ich aber auch noch nichts über Probleme mit MMC-Karten gehört.
Zum Hängen: Vermutlich hängt er in einer der while(1)-Schleifen in
sd_raw.c fest, weil die Karte aus irgendeinem Grund nicht mehr (richtig)
antwortet. Du könntest mal die Datei sd_raw.c aus mega-eth verwenden, da
habe ich diese Warteschleifen zeitlich schon begrenzt. Überhaupt sind
noch einige Rückportierungen von mega-eth nach sd-reader in der
Warteschleife.
Gruß,
Roland
Hallo allerseits,
ich wollte jetzt mal wieder meinen neuen Stand posten.
Also, ich kann jetzt auf die Speicherkarten schreiben und lesen mit FAT.
Das Problem liegt dabei an dem Root-Verzeichnis. Dort hängt er sich
immer auf. Erstelle ich jedoch Unterordner, läuft alles ohne Probleme.
Dort kann ich dann, wie von mir gewünscht,Ordner erstellen, Dateien
erstellen, dort hinein schreiben und die Dateien dann auf einem PC
öffnen.
Das Problem liegt jetzt aber daran, dass ich sie nur unter Linux lesen
kann. Windows gibt immer sie Fehlermeldung, dass die Datei beschädigt
ist.
Ich erstelle .txt dateien und habe es mit Notepad und Editor probiert.
Beides ohne Erfolg.
Hat jemand auch so etwas bemerkt? Woran könnte das liegen? Damit wär mir
schon gut geholfen.
Vielen Dank.
gruß
Thomas
Hallo Thomas,
Du hast schon die neueste sd-reader-Version? Ältere Ausgaben hatten
Fehler wie von Dir beschrieben, die aktuellste eigentlich nicht. Führst
Du vor dem Entfernen der Karte ein sd_raw_sync() ("sync" auf der
Kommandozeile) aus?
(Hoffentlich komme ich demnächst endlich mal dazu, einige
Aktualisierungen zu veröffentlichen.)
Gruß,
Roland
So, heute habe ich die versprochenen Verbesserungen auf meiner Homepage
veröffentlicht und hänge sie jetzt auch wieder an dieses Posting an.
Die Änderungen u.a.:
- Neuer Befehl "init" initialisiert und öffnet die Karte neu.
- Viel höhere Geschwindigkeit beim Durchsuchen bzw. Auflisten von
Verzeichnisinhalten.
- Suche in Verzeichnissen mit mehr als einem Cluster korrigiert.
- Lesen von Verzeichniseinträgen korrigiert, die über eine Clustergrenze
reichen.
- Breche bei zu langen Dateinamen nicht den ganzen LFN-Eintrag ab,
sondern lasse nur einzelne Zeichen weg.
- Reduktion der Codegröße durch zentralisierte Berechnung der
Clusteradressen.
- Einige andere Korrekturen und Optimierungen.
Viele Grüße,
Roland
Guten Tag zusammen
Ich habe eine kurze Frage zur File Erstellung bei bei Rolands Sd-Reader.
Ist es normal das ich ein File z.B test.txt nur in einem Ordner ablegen
kann?
Zuerst wollte ich es direkt auf der root Partition ablegen aber dies
funktionierte leider nie. Also habe ich einen Ordner erstellt, in diesem
anschliessend das File abgelegt und siehe da es funktioniert.
Ich bin mir ziemlich sicher das ich irgendwo noch einen Fehler mache.
Aber ich weis leider momentan nicht wo.
Ich hoffe jemand kann mir ein paar Tipps geben.
Gruss Mathias
Hallo Mathias,
Doch, das Anlegen von Dateien im Wurzelverzeichnis sollte ohne Probleme
funktionieren, schließlich kann man dort ja auch Verzeichnisse anlegen
und das ist im Prinzip auch nichts anderes.
Wie hast Du es denn probiert, von der UART-Kommandozeile aus oder mit
einem eigenen Programm? Kannst Du im letzten Fall den Quelltext bzw.
einen Ausschnitt davon posten?
Gruß,
Roland
Ja da hast du recht, ich habe bereits selbst einmal eine Datei im
Wurzelverzeichnis angelegt. Dies war allerdings mit dem
UART-Kommandozeilen Programm.
Nun habe ich ein eigenes Programm versucht zu erstellen und dort hatte
ich allerdings Probleme.
Was allerdings komisch ist, ist das ich einen Ordner anlegen kann aber
keine Datei.
Hier ein kleiner Teil des Codes:
1
structfat16_dir_struct*dir=0;
2
3
while(1)
4
{
5
if(Taster_Enter_pos_F)
6
{
7
structfat16_dir_entry_structfile_entry;
8
fat16_create_file(dir,"test.kml",&file_entry);
9
sd_raw_sync();
10
}
11
}
Ich danke dir für deine Hilfe, wirklich klasse Support.
Gruss
Das kann so auch nicht funktionieren, da Du fat16_create_file() mit dem
ersten Argument einen Null-Pointer übergibst.
Schau mal in der main.c vom sd-reader nach, dort wird das
Wurzelverzeichnis geöffnet. Dieses Handle auf das Wurzelverzeichnis
übergibst Du dann fat16_create_file(), dann funktioniert es auch. Woher
sonst sollte die Funktion sonst wissen, in welchem Verzeichnis Du die
Datei erzeugen willst?
Gruß,
Roland
gefunden und das entsprechende "< 4085" auskommentiert habe. So viele
Cluster gibt es anscheinend auf einer 8MB-Karte nicht.
Jetzt habe ich aber das Problem, dass ich auf der frisch formatierten
Karte eine Datei anlegen will (und dort auch etwas reinschreibe) und die
Datei dann in Windows aber nicht gelesen werden kann (über das
UART-Interface geht´s aber).
Ich führe dann ein CheckDisk ("Auf Fehler überprüfen") durch, was die
Datei (meistens) wieder herstellt.
Danach kann ich auch weitere Dateien anlegen, die dann problemlos
gelesen werden können.
Hier noch die Karteninfo:
1
manuf:0x01
2
oem:PA
3
prod:S008B
4
rev:41
5
serial:0x39d181e1
6
date:9/3
7
size:6799360
8
copy:0
9
wr.pr.:0/0
10
format:0
11
free:6725632/6760448
Könnte das Problem nur an der geringen Größe der Karte liegen?
Gruß
Markus
Hallo Markus,
Wie formatierst Du die Karte denn? Vielleicht legt Windows bei der
geringen Größe ein FAT12- und kein FAT16-Dateisystem an. Das würde auch
erklären, warum Du die Bedingung bzgl. der Clusteranzahl auskommentieren
musstest (die ja durchaus ihren Sinn hat, denn bei FAT12 kann es netto
eben bis zu 4084 Cluster geben).
Gruß,
Roland
Hallo Roland!
Hast Recht.
Windows legt eine FAT12 an (hab ich mir mit "WinHex" angeschaut).
Nur: Wie kann ich trotzdem ne FAT16 formatieren?
Hab mittlerweile eine größere Karte (256MB) geliehen, jedoch bleibt
diese in der Initialisierung (fat16_open.... partition/device_read
irgendwo hängen).
Muss das nochmal genauer analysieren, wo es hakt.
Gruß & Danke für deine Hilfe
Markus