Hallo!
Ich arbeite derzeit an einem Projekt eine Art Datenlogger zu bauen.
Dabei sollen zyklisch immer wieder Daten auf eine microSDHC-Karte
geschrieben werden.
Ich verwende Elm Chans FAT Bibliothek und diese funktioniert ja auch
teilweise nicht so schlecht. Die Funktionen disk_initialize, disk_read
und disk_write habe ich geschrieben und scheinen auch zu
funktionieren.Die Funktionen disk_status und disk_ioctl habe ich derzeit
noch nicht geschrieben, da diese meiner Meinung nach für mich nicht
notwendig sind.
Nun zum eigentlich Problem:
Ich mit dem Befehl f_open() eine Datei erzeugen. Möchte in diese Datei
dann aber auch gleich Daten rein schreiben, bekomme ich als return value
2 (FR_INT_ERR, Definition siehe unten)* zurück.
Erzeuge ich die Datei mit dem f_open() Befehl, nimm dann die Karte
stecke sie in den Computer und verändere die Datei und probier dann
wieder Daten mit dem Mikrocontroller in die Datei zuschreiben,
funktioniert es. Auch das Auslesen einer Datei mittels f_read() und das
Speichern der gelesen Daten, in einer zuvor am Computer bearbeiten
Datei, funktioniert.
Ich kann mir den Fehler leider nicht wirklich erklären und auch die
Suchfunktion hat mich leider noch nicht zur Lösung geführt.
Vielleicht hatte von euch schon jemand einmal dieses Problem oder kann
mir generell Tipps geben, woran es liegen könnte.
*Definition von FR_INT_ERR:
Assertion failed. An insanity is detected in the internal process. One
of the following possibilities is suspected.
- Work area (file system object, file object or etc...) is broken by
stack overflow or any other application. This is the reason in most
case.
- There is any error of the FAT structure on the volume.
Note that if once this error occured at any operation to an open file,
the file object is aborted and all operations to the file except for
close will be rejected.
Update:
Ich habe mir nun mit dem Debugger mal angeschaut, woher im Code die
Fehlermeldung kommt
1
<snip>
2
caseFS_FAT16:
3
if(move_window(fs,fs->fatbase+(clst/(SS(fs)/2))))
4
break;
5
p=&fs->win[clst*2%SS(fs)];
6
returnLD_WORD(p);
7
8
caseFS_FAT32:
9
if(move_window(fs,fs->fatbase+(clst/(SS(fs)/4))))
10
break;
11
p=&fs->win[clst*4%SS(fs)];
12
if(LD_DWORD(p)&0x0FFFFFFF)//<- diese Bedingung wird nicht erfüllt
13
returnLD_DWORD(p)&0x0FFFFFFF;
14
15
default:
16
return1;//<- somit wird 1 zurückgegeben
17
}
18
<snip>
Jedoch verstehe ich nicht was hier genau passiert bzw. passieren sollte.
Ich werde mich noch weiter damit beschäftigen, aber vielleicht kann mir
von euch ja jemand eine Menge Zeit sparen.
LG Chris
>volatile void* read_buff[20];
Das scheint mir komisch, das ist ein Array von Pointern! Eher so
>volatile uint8_t read_buff[20];
Du musst nicht in den Innereien vom FATfs rumstochern, das passt schon.
Wie sieht dein Hardwareaufbau aus?
>Das scheint mir komisch
Da hast du recht... schon ausgebessert
Bei meinem Hardwareaufbau ist einfach jede Datenleitung(MISO, MOSI, und
auch die unbenutzten "Datenleitungen") und auch die CLK-Leitung über
einen Pullup-Widerstand mit 3,3V verbunden. Die Versorgung erfolgt über
den das Mikrocontrollerboard, welches über ein JTAG-Interface gespeist
wird.
Die Datenleitungen sind dann über einen einfachen Buchsenstecker und
Stiftleiste mit dem Controller verbunden.
Die Leitungen rechts waren nur für die ersten Versuche um ein
Oszilloskop anzuschließen.
LG Christoph
@Christoph H. (hoc)
>Bei meinem Hardwareaufbau ist einfach jede Datenleitung(MISO, MOSI, und>auch die unbenutzten "Datenleitungen") und auch die CLK-Leitung über
Naja, nicht wirklich gut aber auch nicht wirklich schlecht.
Aber warum öffnest du mit FA_WRITE | FA_READ | FA_CREATE_ALWAYS, wenn du
nur schrieben willst. Probier erstmal nur
FA_WRITE | FA_CREATE_ALWAYS
Letztens hatte jemand Probleme mit schlechter Hardware.
Ich werd es dann gleich mal ausprobieren, aber ich denke mal, dass das
FA_READ nur von einem anderen Versuch übergeblieben ist.
Dies ist nur eine Übergangslösung. Heute bzw. morgen sollte mein PCB
kommen und dann fällt auch dieser schwindelige Aufbau weg.
Was noch vergessen habe zu sagen... momentan habe ich es mit zwei
verschiedenen Kartenherstellern probiert und bei beiden tritt der
gleiche Fehler auf. Kann es vielleicht doch sein, dass sich in den von
mir geschriebenen Funktionen ein Fehler eingeschlichen hat?
Code folgt natürlich noch
LG Christoph
Christoph H. schrieb:> Kann es vielleicht doch sein, dass sich in den von> mir geschriebenen Funktionen ein Fehler eingeschlichen hat?
Selbst das ist nicht völlig auszuschließen…
Es gibt keinen Grund, FAT- Funktionen selbst zu schreiben. Nimm das
komplette Projekt von Elm-Chan in der neuesten Version 10b. Dann
funktioniert das auch.
Grundschüler schrieb:> Es gibt keinen Grund, FAT- Funktionen selbst zu schreiben. Nimm das> komplette Projekt von Elm-Chan in der neuesten Version 10b. Dann> funktioniert das auch.
Was für ein Blödsinn, die Hardwareanbindung muss er deswegen trotzdem
schreiben, das nimmt ihm das Projekt nicht ab.
sendByteSPI(DUMMY_FF);//last transmitted data byte
63
response=sdGetResponse();
64
res=checkResponseR1(response);
65
if(res!=0)
66
{
67
checkBusy();
68
returnres;
69
}
70
}
71
SD_CS_HIGH;
72
returnres;
73
74
}
und noch die write Funktion
1
DRESULTdisk_write(
2
BYTEpdrv,/* Physical drive nmuber (0..) */
3
constBYTE*buff,/* Data to be written */
4
DWORDsector,/* Sector address (LBA) */
5
UINTcount/* Number of sectors to write (1..128) */
6
)
7
{
8
DRESULTres;
9
intcounter;
10
intblock_num=0;
11
charresponse=0x00;
12
13
//res = disk_status check!!! should be there
14
//if(res == STA_NOINIT)
15
// return RES_NOTRDY;
16
17
if(!count)
18
returnRES_PARERR;
19
20
nextCmd();
21
22
if(count==1)
23
{
24
sdSendCmd(WRITE_SINGLE_BLOCK,sector,DUMMY_FF);
25
response=sdGetResponse();
26
res=checkResponseR1(response);
27
if(res!=0)
28
returnres;
29
30
for(counter=0;counter<8;counter++)
31
{
32
sendByteSPI(DUMMY_FF);
33
}
34
35
sendByteSPI(DATA_START_TOKEN_S);
36
37
for(counter=0;counter<512;counter++)
38
{
39
sendByteSPI(buff[counter]);
40
}
41
sendByteSPI(DUMMY_FF);
42
sendByteSPI(DUMMY_FF);//2 times CRC16
43
44
if(sendByteSPI(DUMMY_FF)&0x08)//check data response token
45
returnRES_ERROR;
46
47
checkBusy();
48
}
49
else
50
{
51
sdSendCmd(WRITE_MULTIPLE_BLOCK,sector,DUMMY_FF);
52
response=sdGetResponse();
53
res=checkResponseR1(response);
54
if(res!=0)
55
returnres;
56
57
for(block_num=0;block_num<count;block_num++)
58
{
59
for(counter=0;counter<8;counter++)
60
{
61
sendByteSPI(DUMMY_FF);
62
}
63
64
sendByteSPI(DATA_START_TOKEN_M);
65
66
for(counter=0;counter<512;counter++)
67
{
68
sendByteSPI(buff[block_num*512+counter]);
69
}
70
sendByteSPI(DUMMY_FF);
71
sendByteSPI(DUMMY_FF);//2 times CRC16
72
73
if(sendByteSPI(DUMMY_FF)&0x08)//check data response token
74
returnRES_ERROR;
75
76
checkBusy();
77
}
78
for(counter=0;counter<8;counter++)
79
{
80
sendByteSPI(DUMMY_FF);
81
}
82
sendByteSPI(DATA_STOP_TOKEN);
83
84
checkBusy();//while(!sendByteSPI(DUMMY_FF));
85
86
87
}
88
SD_CS_HIGH;
89
returnres;
90
}
Ich ahbe den Code nun auch mit
FA_WRITE | FA_CREATE_ALWAYS
ausprobiert und bin leider nur zum gleichen Ergebnis (FR_INT_ERR)
gekommen.
Was könnte man an der Hardware besser machen?
Auf meinem eigentlich Board gibt es noch eine Spule in der
Versorgungsleitung, sowie einen Kondensator parallel dazu. Eigentlich
der fast der gleiche Aufbau, wie ich ihn hier im Forum
(Beitrag "Re: SD-Karte abschalten durch Trennen der Versorgung funktioniert nicht") gefunden habe.
Ich hätte an einen 1-by-off error gedacht, so dass der Treiber dann
vielleicht eine Information zu einer Datei nicht findet und diese so
nicht beschrieben kann.
Ich gebe leider zu ich habe keine Ahnung vom Dateisystem FAT32, aber ich
finde auch im Internet relativ wenig dazu.
Ich habe den Code nun auch mit
FA_WRITE | FA_CREATE_ALWAYS
ausprobiert und bin leider nur zum gleichen Ergebnis (FR_INT_ERR)
gekommen.
Was könnte man an der Hardware besser machen?
Auf meinem eigentlich Board gibt es noch eine Spule in der
Versorgungsleitung, sowie einen Kondensator parallel dazu. Eigentlich
der fast der gleiche Aufbau, wie ich ihn hier im Forum
(Beitrag "Re: SD-Karte abschalten durch Trennen der Versorgung funktioniert nicht") gefunden habe.
Im Anhang findet sich der Code für meine Funktionen...
LG Christoph
edit: Ich kann den letzten Beitrag von mir leider nicht löschen. Sorry,
für die unschöne Form, welche der Beitrag dadurch erhalten hat
Finnsnes schrieb:> Was für ein Blödsinn, die Hardwareanbindung muss er deswegen trotzdem> schreiben, das nimmt ihm das Projekt nicht ab.
Die Hardwareanbindung muss er nicht selbst schreiben sondern allenfalls
das Pinout und die Spi-Schnittstelle anpassen.
Der einfachste und sicherste Weg ist - wie der Name sagt - chans
avr_foolproof. Da müssen nur die Definitionen für das Bitbanging
geändert werden. Wenn das nicht funktioniert, liegt es an der Hardware.
Wenn es funktioniert kann der lowlevel-Teil ersetzt werden. Im Prinzip
besteht der zu ändernde lowlevel Teil nur aus spi_xmit und spi_rsvr. An
den Funktionen
disk_initialize, disk_read und disk_write muss man nichts ändern.
Die Pullups an sck, mosi und cs sind völlig sinnlos und eher schädlich,
weil der uc dagegen anarbeiten muss. Über den pullup an miso kann man
geteilter Meinung sein. Normalerweise reicht der interne uc-pullup
völlig aus.
@Grundschüler (Gast)
>Die Pullups an sck, mosi und cs sind völlig sinnlos und eher schädlich,>weil der uc dagegen anarbeiten muss.
Quark. Es sind Pull-Ups, keine Leistungswiderstände. Dort sind ein paar
Dutzend kOhm dran, das interessiert den AVR keine Sekunde.
Ausserdem braucht CS einen externen Pull-Up, damit die SD-Karte still
ist, wenn der AVR per ISP programmiert wird!
> Über den pullup an miso kann man>geteilter Meinung sein.
Nein, das kann man NICHT!
> Normalerweise reicht der interne uc-pullup völlig aus.
Schon wieder falsch! Nicht nur, dass die Spezifikation einen eher
niederohmigen Pull-Up verlangt, eben weil dieser Ausgang vor der
Initialaisierung ein Open Drain Ausgang ist, nein auch praktisch zeigt
sich, dass mit 30-50kOhm internen Pull-Up das Ganze nur sehr
unzuverlässig funktioniert.
Ergo. Mach deinem Namen Ehre und geh nochmal zu elektronischen
Grundschule.
hei,
hast du im Sourcecode die 4 define für die Port's entsprechen deiner
Hardware angepaßt?
schönen Tag
mal auf die schnelle
#define CS_LOW()
#define CS_HIGH()
OK... also ich verwende leider keinen AVR sondern einen Controller aus
der MSP430 Familie. Ob damit das Portieren von avr_foolproof noch so
einfach geht?
Falls es doch geht: @Grundschüler:
Also muss ich da eigentlich nur ein Software SPI realisieren in dem ich
einfach meine Ports in den Definition austausche? Da kommt dann aber
noch das F_CPU... Was soll ich da eintragen... das ist mir gerade nicht
klar.
@Falk:
Ich verwende, wie oben schon einmal gezeigt, die Schaltung aus den
Beitrag und habe somit 47k Ohm als Pullups. Meinst du sollte ich hier
einen niedrigeren Wert verwende?
@L.R.
Ich habe in der importierten Bibliothek kein CS_LOW() oder CS_HIGH().
SD_CS_HIGH und SD_CS_LOW habe ich selber definiert und die funktionieren
auch.
Mich wundert einfach nur, dass ich eigentlich alles machen kann, aber
ich kann einfach nicht in ein leeres z.B. Textdokument schreiben. Sobald
ich einmal einen Buchstaben im File habe, kann ich alles machen.
>Also muss ich da eigentlich nur ein Software SPI realisieren in dem ich>einfach meine Ports in den Definition austausche?
Nein, wozu? Wenn dein Hardware SPI läuft ist doch alles gut.
hei,
läuft bei mir auf einem PIC32MX..
Beispiele waren nur auf die schnelle.
Steht bei mir in der mmcPIC32 ..
Hatte es sofort nach den Anpassungen zum laufen gebracht.
schönen Abend
@Christoph H. (hoc)
>der MSP430 Familie. Ob damit das Portieren von avr_foolproof noch so>einfach geht?
Ich denke schon.
>Also muss ich da eigentlich nur ein Software SPI realisieren in dem ich>einfach meine Ports in den Definition austausche?
Wenn deine Software schon fast alles kann, ist das sinnlos. Das Problem
liegt woanders.
>Ich verwende, wie oben schon einmal gezeigt, die Schaltung aus den>Beitrag und habe somit 47k Ohm als Pullups. Meinst du sollte ich hier>einen niedrigeren Wert verwende?
Für MISO sollte man 2-10k nehmen.
>ich kann einfach nicht in ein leeres z.B. Textdokument schreiben. Sobald>ich einmal einen Buchstaben im File habe, kann ich alles machen.
Komisch.
Ich werde jetzt zuerst noch einmal die Portierung vom avr_foolproof
probieren und dann geh ich an die Hardware und werde den Pullup ändern.
Danke schon einmal für die zahlreichen Antworten :)
Falk Brunner schrieb:> Ergo. Mach deinem Namen Ehre und geh nochmal zu elektronischen> Grundschule.
Gerne. Erklär doch mal, was der Pullup an sck bewirken soll. Bei
Spi-mode0 ist der Ruhezustand 0. Der Pullup an sck ist definitiv falsch,
steht nicht in der Spezifikation und widerspricht dem bei Chan zu
findenden Schema.
Christoph H. schrieb:> Also muss ich da eigentlich nur ein Software SPI realisieren in dem ich> einfach meine Ports in den Definition austausche? Da kommt dann aber> noch das F_CPU... Was soll ich da eintragen... das ist mir gerade nicht> klar.
F_CPU ist für den software-spi egal, weil er eh sehr langsam ist. Ich
habe es bei einem 168Mhz-F4 auspropiert. Du kannst aber auch jeden
einzelnen Takt verzögern, indem du bei ck_h/l delays einbaust:
1
#define ck_port C
2
#define ck_pin 10
3
#define do_port C
4
#define do_pin 11
5
#define di_port C
6
#define di_pin 12
7
#define cs_port C
8
#define cs_pin 9
9
10
//sck
11
#define CK_INIT() pinDIRout(ck_port,ck_pin) /* Initialize port for MMC SCLK as output */
Christoph H. schrieb:> Erzeuge ich die Datei mit dem f_open() Befehl, nimm dann die Karte> stecke sie in den Computer und verändere die Datei und probier dann> wieder Daten mit dem Mikrocontroller in die Datei zuschreiben,> funktioniert es. Auch das Auslesen einer Datei mittels f_read() und das
Wahrscheinlich ein Problem mit FAT #2, aber nur zur Sicherheit -
wie gross sind deine SD-Karten ?
Mit der Portierung tu ich mir leider gerade doch etwas schwer. Hatte
aber gestern fast keine Zeit mich damit zu beschäftigen.
Habe mich jetzt aber doch für den Hardwae SPI entschieden, da dieser ja
ohne Probleme funktioniert.
Der Pullup an der Clock-Leitung war ein Fehler von mir. Habe beim
"abkupfern" der Schaltung einen Fehler gemacht. Der Pullup wurde aber
gestern noch gegen einen Pulldown ausgetauscht, was aber keinerlei
Unterschied macht, Fehler bleibt der gleiche.
Es wäre aber doch auch ziemlich komisch, wenn ich alles schreiben und
lesen kann (unter den genannten Vorraussetzungen) , dass es an der
Beschaltung liegt?!
@Vesely:
Die karten sind eine Transcend 8GB und eine SanDisk 8GB und 4GB.
Bei allen tritt das gleiche Problem auf.
@ Chris H. (hoc)
>Es wäre aber doch auch ziemlich komisch, wenn ich alles schreiben und>lesen kann (unter den genannten Vorraussetzungen) , dass es an der>Beschaltung liegt?!
Ja. Es kann auch ein Konfigurationsproblem im FatFs sein.
Chris H. schrieb:> Die karten sind eine Transcend 8GB und eine SanDisk 8GB und 4GB.> Bei allen tritt das gleiche Problem auf.
Probiere es mit 1GB, nur um sicher zu gehen.
Chris H. schrieb:> Habe beim "abkupfern" der Schaltung einen Fehler gemacht.
die Pullups - mit nur 47k - sind sicher nicht das Problem. Es ist aber
immerhin interesssant, dass dein sck-Pulldown auf die
Schaltungsempfehlung von chan aus 2010 zurückgeht. Inzwischen hat chan
das geändert. Es gibt keinen sck-pulldown mehr. Vermutlich hat er sich
etwas dabei gedacht.
Chris H. schrieb:> Die Funktionen disk_initialize, disk_read> und disk_write habe ich geschrieben
Da du an diesen Funktionen zumindest etwas geändert hast, liegt der
Fehler am wahrscheinlichsten an deinen Änderungen. Solche Fehler zu
finden, ist extrem schwierig weil man deine Änderungen nachvollziehen
müsste. Deswegen die Empfehlung, Original-Chan neu zu installieren. Ob
sw- oder hw-spi ist relativ egal. Hauptsache es ist der Code von Chan
ohne Änderungen von dir, die über die Anpassung des lowlevel-pinouts
hinausgehen.