Forum: Projekte & Code MMC SD library FAT16 FAT32 read write


von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

hallo,

hier mal meine fat16/fat32 lib für atmel atmegas.
noch ich sag mal im alpha 2 status ;)

was geht ist:

- auslesen eines MBR ( muss im code eingestellt werden...)

- datei anlegen        open('w',rstr);
- datei schreiben      ffwrite(c);
- datei anhängen       open('a',rstr);
- datei lesen          c=ffread();
- datei löschen        ffrm(fileName);
- direktory wechseln   ffcd(dirName);  (immer nur eins nach dem anderen)
- direktory anzeigen   ffls();
- datei seek           ffseek(234);    (ab stelle 0, nur beim lesen)

- commando promt    hier kann komplette funktionalität getestet werden !
- umwandeln von "t.txt" -> "T        TXT"    fat_str("t.txt);


mit einem atmega168 @ 20 mhz schafft man lesend ~ 220.000 bytes/sec,
mit einem atmega32  @ 8  mhz schafft man lesend ~  20.000 bytes/sec,
bei fat 32 mit größeren clustern wird es immer schneller ;)

würde mich über anregungen, oder verbesserungsvorschläge freuen !

ps: hab Ulrich Radigs mmc.h/mmc.c etwas erweiter, an dieser stelle danke
    für die veröffentlichung dieser dateien.

grüße daniel

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

hallo,

einige bug-fixes sind gemacht, eine lib zum einlesen von
tastatureingaben, über eine at-tastatur ist jetzt dabei.

nur falls es jemanden interessiert ;)

von Alexander D. (zebprophet)


Lesenswert?

g das thema interessiert doch immer.

wie sieht es mit dem speicherbedarf aus? funktioniert der code auch - 
read only - auf einem atmega16 (1kb ram)?

von gast (Gast)


Lesenswert?

mich würde nicht nur der quelltext, sondern auch deine quellen 
interessieren, gerade spezifikation, umsetzung mit atmega etc.

von Daniel R. (zerrome)


Lesenswert?

hallo,

@ Alexander D.

würde sogar mit write funktionieren, man müsste nur in der main auf ein 
paar sachen verzichten, wie den commando prompt und so. nur die 
fat-0.x.c und file-0.x.c sind auch super so zu gebrauchen.

@ gast

quellen sind einmal die Fatgen103.pdf spezifikationen von MS gewesen und

https://www.pjrc.com/tech/8051/ide/fat32.html

entickelt hab ich das ganze mit linux.
habe mir raw images von mmc/sd karten gemacht und das mit 
low-level-datei-lese funktionen mit linux gcc geschrieben, da kann man 
dann schön debugen.


zu dem code,
das einzige problem, warum read und write nich z.b. auf einem atmega8 
läuft ist, weil nicht genügend flash da ist, ram würde locker reichen.

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

hallo,

neue optimierungen und bugs beseitigt beim schreiben !

fat16 schreiben von 60.000 bytes in 1,421 sec -> 41KB
fat16 lesen     von 60.000 bytes in 0,823 sec -> 71KB

fat32 schreiben von 60.000 bytes in 1,249 sec -> 46KB
fat32 lesen     von 60.000 bytes in 0,747 sec -> 78KB


die werte, mit atmega32 @ 8 mhz (interner takt).

status: ist jetzt voll funktionsfähig !


grüße daniel

von Siegmar (Gast)


Lesenswert?

Hallo

Habs zwar noch nicht testen können, sieht aber Klasse aus !!
Tolle Arbeit !!!
Noch einen schönen Abend
Gruß
Siegmar

von holger (Gast)


Lesenswert?

>#include "fat-0.3.c"
>#include "file-0.3.c"

Das macht man nicht ;) Gibt nur Probleme.
Bastel dir mal eine fat.h und file.h.

von Daniel R. (zerrome)


Lesenswert?

hallo,

@  Siegmar

danke, hört man gerne :)
wenn du zum testen kommst, laß doch mal hören wo es hinkt,
wenn es hinkt ;)

@ holger

ja werd ich machen. nur noch keine lust gehabt...
ist mir auch noch ein kleines rätsel warum das unbedingt nötig ist.
würde es reichen nur die funktionen in einer *.h datei "bekannt" zu 
machen, die von anderen *.c dateien aus aufgerufen werden ? das würde 
für mich am meisten sinn machen. wäre dann quasi sowas wie private oder 
public. also private nur in der *.c selber als prototyp, public in der 
*.h...

von kalhou (Gast)


Lesenswert?

Da ich mich momentan auch gerade mit dem Thema befasse, werde ich die 
Library mal ausprobieren. Ich hab aber gehört, dass FAT32 auf SD-Karten 
nicht funktioniert ? Oder ist nur ein Gerücht ?

von Daniel R. (zerrome)


Lesenswert?

hallo,

@ kalhou

es kommt auf die größe der karte an. manche sind zu klein um sie mit 
fat32 zu formatieren. andere wieder sind zu groß um sie mit fat 16 zu 
formatieren...
welchen controller willst du denn benutzen und wie willst du die karte 
anschließen?

grüße daniel

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

hallo,

kleinere änderungen, grad der optimierung erhöht.

ohne lcd, tastatur und benchmark teil,
jetzt 709 bytes statischer ram (bei lesen und schreiben mit commando 
prompt) und 10127 bytes an flash speicher verbrauch.
mit allem 740 ram und 11796 flash.

compiler optimierung 2 besser als s...


grüße daniel

von kalhou (Gast)


Lesenswert?

Die Karte hängt an einem atmega128 momentan ist sie über hardware spi 
angeschlossen... d.h. 1Gb sollte mit FAT32 funktionieren ?

von kalhou (Gast)


Lesenswert?

So... hab jetzt die Library mal ausprobiert.

Zuerst hatte ich Probleme, da ich das Ganze in AVR-Studio probierte und 
daher kein Makefile verwendete, dass mir Studio diverse Fehler 
zurückgab, die sich mit der Einbindung eines Makefiles praktisch in Luft 
auflösten.
Trotzdem wäre es von Vorteil wenn es auch ohne die Einbindung eines 
externen Makefiles funktionieren würde ;)

Weiter habe ich dann probiert ein paar Zeichen aus einer Datei zu lesen.
1
#include <stdlib.h>
2
#include <string.h>  
3
#include <avr/io.h>
4
#include <avr/pgmspace.h>  
5
#include <avr/interrupt.h>      
6
7
#define F_CPU 14745600UL
8
#include <util/delay.h>
9
10
#include "uart-0.1.h"      
11
#include "mmc-0.2.h"      
12
#include "fat-0.3.h"      
13
#include "file-0.3.h"  
14
15
#define BUFF_SIZE 15  
16
unsigned char kb_buffer[BUFF_SIZE];  
17
18
int main(void){
19
  DDRA = 0xFF;
20
  PORTA = 0x00;
21
22
  uinit(); 
23
      
24
  uputs("Boot ok\n\r");
25
26
  if (mmc_init() == 0){       //ist der Rückgabewert ungleich NULL ist ein Fehler aufgetreten  
27
  uputs("SD Init ok\n\r");
28
  } 
29
  else{
30
  uputs("SD Init failed\n\r");
31
  }
32
33
  if(0==fat_initfat()){
34
     uputs("FAT Init ok\n\r");    
35
   }
36
  else{
37
    uputs("FAT Init failed\n\r");
38
  }
39
40
  //Datei lesen
41
  ffopen('r',"delme.txt");
42
43
  uputc(fread());
44
  uputc(fread());
45
  uputc(fread());
46
  uputc(fread());
47
  uputc(fread());
48
  uputc(fread());
49
  uputc(fread());
50
  uputc(fread());
51
  uputs("\n\r");
52
  ffclose();
53
54
  for(;;){
55
    PORTA = 0xFF;
56
  }
57
}

Das Init Zeugs hat funktioniert und wurde mir auch schön auf der UART 
angezeigt. Scheint das lesen der Datei nicht zu funktionieren.

Was ich noch vermisse ist eine Funktion zum beschreiben der Dateien, 
sowie eine Funktion zum lesen ganzer Strings ;)

von Daniel R. (zerrome)


Lesenswert?

hallo,

@ kalhou

also beschreiben einer datei würde wie folgt laufen:
1
//1
2
ffopen('w',"DELME   TXT");                      
3
                               
4
//2
5
unsigned char str[22]="das soll auf die karte";           
6
unsigned char i=0;
7
8
//3
9
do{
10
11
   ffwrite(str[i]);
12
   i++;
13
}while(str[i]!='\0');
14
15
//4
16
ffclose();

-1 die funktion ffopen erwartet als datei bezeichnung einen string im 
8.3 format, alles großgeschrieben ! man kann zum wandeln von z.b. 
delme.txt" die funktion fat_str nutzen, die macht aus "delme.txt" "DELME 
TXT".

-2 str enthält 22 bytes die auf die karte sollen, i ist nur ein index 
zähler für den str

-3 in der schleife wird auf die karte geschrieben, der ganze string

-4 schließt die datei (erst hier wird die datei tatsächlich angelegt, 
vorher werden nur die daten der datei auf die karte geschrieben)

noch zu 1:
es gibt auch noch ffopen('a',"DELME   TXT"); das würde die datei zum 
anhängen öffnen, wird dann ab letztem zeichen weiter geschrieben.

nur öffnen zum lesen wäre ffopen('r',"DELME   TXT"); und dein obiger 
code

von kalhou (Gast)


Lesenswert?

Zum Verständniss: verwendet habe ich die aktuellste Version 
"mmc-0.3.1.zip" dort findet sich leider keine Funktion "fat_str"
1
#include <stdlib.h>
2
#include <string.h>  
3
#include <avr/io.h>
4
#include <avr/pgmspace.h>  
5
#include <avr/interrupt.h>      
6
7
#define F_CPU 14745600UL
8
#include <util/delay.h>
9
10
#include "uart-0.1.h"      
11
#include "mmc-0.2.h"      
12
#include "fat-0.3.h"      
13
#include "file-0.3.h"  
14
15
#define BUFF_SIZE 15  
16
unsigned char kb_buffer[BUFF_SIZE];  
17
18
int main(void){
19
  DDRA = 0xFF;
20
  PORTA = 0x00;
21
22
  uinit(); 
23
      
24
  uputs("Boot ok\n\r");
25
26
  if (mmc_init() == 0){       //ist der Rückgabewert ungleich NULL ist ein Fehler aufgetreten  
27
  uputs("SD Init ok\n\r");
28
  } 
29
  else{
30
  uputs("SD Init failed\n\r");
31
  }
32
33
  if(0==fat_initfat()){
34
     uputs("FAT Init ok\n\r");    
35
   }
36
  else{
37
    uputs("FAT Init failed\n\r");
38
  }
39
40
  //Datei schreiben
41
  
42
  //1
43
  ffopen('w',"DELME   TXT");                      
44
                               
45
  //2
46
  unsigned char str[22]="das soll auf die karte";           
47
  unsigned char i=0;
48
49
  //3
50
  do{
51
52
   ffwrite(str[i]);
53
   i++;
54
  }while(str[i]!='\0');
55
56
  //4
57
  ffclose();
58
59
60
  for(;;){
61
    PORTA = 0xFF;
62
  }
63
}

Das Beispiel hier funktioniert nur soweit ich keine Datei auf der Karte 
habe die "delme.txt" heisst!
Wenn ich eine Datei "delme.txt" auf der Karte habe und dann mit dem 
Modus 'a'  den String dranhängen will, klappt das nicht und der 
Kontroller bleibt hängen (zu sehen an den LEDS (PORTA) die nie angehen.

Das lesen schlug in beiden fällen Fehl.

1. Heisst das also, dass man soweit nur Files in Grossbuchstaben ablegen 
kann ?
2. Warum wurde die fat_str Funktion nicht direkt in fopen integriert ?
3. Wird es in naher Zukunft noch Funktionen geben zum direkten 
Lesen/Schreiben von Strings ?
4. Wird es ebenfalls in naher Zukunft die Möglichkeit geben mehrere 
Dateien zu öffnen ? Wäre ja eigentlich keine Sache, da man nur bei fopen 
eine File Struktur zurückgeben und bei jeder Funktion wie fread auf den 
Zeiger auf diese Struktur zugreifen müsste :)

von Daniel R. (zerrome)


Lesenswert?

hallo,

sieh dir mal mit einem hex editor die daten auf der karte an.

da wirst du sehen, dass dort 8.3 einträge und lange datei namen drauf 
sind.
bei allen 8.3 datei namen werden großbuchstaben sein. wenn der datei 
name bzw. die endung nicht 8 bzw 3 zeichen haben, wird mit leerzeichen 
aufgefüllt, bis 8.3 erfüllt ist!
wenn du mit dem pc eine datei auf der karte anlegst, dann wird es bei 
dem beispiel "delme.txt" einen 8.3 eintrag geben der "DELME   TXT" 
lautet. nur mit diesen 8.3 namen arbeitet die library.
fat_str ist aus dem grund nicht in ffopen integriert, weil es auch ohne 
läuft und ich das ganze so schrumpfen möchte, das es irgendwann auf 
einen mega8 passt.

-1. egal was für eine datei du anlegst, es wird immer ein großbuchstaben 
8.3 name mit angelegt. von jedem betriebssystem, dass ich kenne.

-3. da ist die funktion zum schreiben von strings...
1
ffwriteString(unsigned char str[],unsigned char name[], unsigned char option){
2
3
  ffopen(option,name);                      
4
  unsigned long int i=0;    
5
6
7
  do{
8
9
   ffwrite(str[i]);
10
   i++;
11
  }while(str[i]!='\0');
12
13
 
14
  ffclose();
15
}
nur so aus dem kopf, sollte aber gehn :)


-4. mehrere dateien wird es erstmal nicht geben, aus ram gründen.
aber du hast doch schon einen weg aufgezeigt wie es gehen könnte. wenn 
du es änderst, poste doch einfach mal eine ergebnisse :)

zu dem problem mit dem anhängen, werd ich später mal ausprobieren...

von Daniel R. (zerrome)


Lesenswert?

hallo,

bei mir gibt es mit folgendem code keine probleme:
1
  // löscht datei, wenn vorhanden...
2
  ffrm("DELME   TXT");    
3
  
4
  // schreibt in die datei (kann nur schreiben wenn nicht vorhanden ist)
5
  ffwriteString("das soll in die datei","DELME   TXT",'w'); 
6
7
  // anhängen von daten
8
  ffwriteString(", mehr noch","DELME   TXT",'a');

benutzt wird die ffwirteString von siehe oben...

wegen dem einlesen von strings kannst du dir ja nach dem beispiel was 
basteln...

grüße daniel

von kalhou (Gast)


Lesenswert?

lesen und schreiben habe ich jetzt soweit geschafft.. werde morgen mal 
weiter schauen...

eine letzte frage bleibt: bei langen dateinamen < 8 zeichen wird das ja 
mit ~1 gemacht.. also z.b. aus "langer-dateiname" wird "langer~1.txt" 
wie funktioniert das allerdings wenn ich zwei "ähnliche" dateinamen habe 
? also z.b. "langedatei1" und "langedatei2" würden ja dann beide mit 
"langed~1" abgekürzt... geht das überhaupt ?

von Daniel R. (zerrome)


Lesenswert?

daraus wird dann: langed~1, langed~2 usw... ist dann etwas 
unübersichtlich ;)

vorallem wenn es so etwas ist wie langedatei-wichtig-von-chef.txt und 
langedatei-wichtig-von-frau.txt weil daraus auch langed~1 und langed~2 
wird

von kalhou (Gast)


Lesenswert?

also wenn ich jetzt "langedatei-wichtig-von-chef.txt" und
"langedatei-wichtig-von-frau.txt" auf der sd habe wie weiss ich dann 
welche datei ich mit "langed~1" resp. "langed~2" anspreche ?

gruss

von Joachim (Gast)


Lesenswert?

> wie weiss ich dann
> welche datei ich mit "langed~1" resp. "langed~2" anspreche ?

Öffnen und nachgucken?

von Kevin K. (kalhou)


Lesenswert?

Dürfte wohl für den Controller weniger einfach werden, anhand des 
Inhaltes einer Datei darauf zu schliessen, wie der originale Dateiname 
lautet. Es sei denn der originale Dateiname steht versteckt irgendwo in 
der Datei, was ich mir aber nicht vorstellen kann!
Das Problem ist ja, dass wenn ich die Datei 
"langedatei-wichtig-von-frau.txt" öffnen will, nicht beide Dateien 
"langed~1" und "langed~2" aufmachen sollte, um herauszufinden welche der 
beiden jetzt die Datei ist die ich brauche.

von holger (Gast)


Lesenswert?

Auf lange Dateinamen sollte man beim uC grundsätzlich
verzichten. Die Auswertung benötigt eine Menge RAM.
Man kommt mit den 8.3 Dateinamen eigentlich immer klar.
Unter DOS war das früher auch nicht anders ;)

von Kevin K. (kalhou)


Lesenswert?

Das Problem ist nur, wenn ich auf meinem MP3-Player eine Datei in Form 
von "Interpret - Titel" ablege, bekomme ich schon mächtig Probleme, da 
z.b. ein Album 10 Lieder drauf hat "Interp~1...10" wird schon ein wenig 
schwierig zum auslesen.

von holger (Gast)


Lesenswert?

>wenn ich auf meinem MP3-Player eine Datei

Ich wusste das du das sagen würdest!
Gut, da macht das Sinn. Welcher 8.3 Name zum
langen Dateinamen gehört ist relativ einfach
rauszufinden: Der 8.3 Eintrag steht direkt hinter
den Einträgen des langen Dateinamens.

von tbd (Gast)


Lesenswert?

oder id3-tags auslesen ;)

von kalhou (Gast)


Lesenswert?

das problem bei den id3 tags ist nur, dass sie unterschiedlicher nicht 
sein könnten. die einen stehen am anfang, die anderen am ende.. di einen 
beginnen mit TAG, die anderen mit id3 etc. das tag auszuwerten ist ja 
noch einfach, da immer 30 bytes reserviert sind.... werds wohl trotzdem 
irgendwie versuchen alle möglichkeiten auszulesen :o

von Daniel R. (zerrome)


Lesenswert?

hallo,

das problem von langen dateinamen ist das die auch mal 255 zeichen lang 
sein können.
ich finde, wenn man z.b. einen mp3 player baut, sollte der auch die id3 
tags anzeigen wenn er die lieder spielt. es git doch pc programme, die 
die mp3 sammlungen sortieren und ordentlich tagen...

grüße daniel

von kalhou (Gast)


Lesenswert?

So, hab jetzt ein bisschen mit der Library herumexpermientiert.
Was ich probiere zu machen ist z.b. mit ffls(); alle Dateien eines 
Verzeichnisses auszulesen und statt mit uart an den PC zu senden, die 
Dateinamen in einer weiteren Datei zwischenzuspeichern. Ist sowas 
theoretisch möglich oder müsste ich dafür mehrere Files offen haben ?
Hab schon ein wenig probiert die Funktionen auf mehrere Files 
umzuschreiben, aber zu der File Struktur die ich jedesmal als Zeiger 
übergeben muss kommt auch noch die Fat Struktur dazu, die ja atm. auch 
statisch ist und welche ich wohl auch irgendwie über einen Zeiger 
mitgeben müsste, aber um das umzuschreiben bin ich mir zu wenig mit dem 
FAT Dateisystem vertraut...

Jemand eine Idee ?

Gruss

von Daniel R. (zerrome)


Lesenswert?

hallo,

die funktion "lsRowsOfClust(unsigned long int start_sec)" in file-0.3.c 
bekommt einen start sektor eines clusters übergeben und arbeitet dann 
selbständig den cluster ab (also die sektoren). und in dieser funktion 
benutzt du einfach anstatt der uart ausgaben, einen teil in dem du die 
namen oder was auch immer dich interessiert von der datei woanders 
speicherst.
in dem teil wo die uart ausgaben sind ist die aktuelle datei auf dem 
struct:file zu finden, mit allen möglichen angaben. in dem struct:fat 
ist der aktuell geladenen sektor zu finden.
macht zusammen: name, attribut, reihe in sektor, den sektor selber, 
größe, länge, 1.cluster. also alles was man zur weiteren verarbeitung 
braucht.

hilft das?

güße daniel

von kalhou (Gast)


Lesenswert?

Das Problem ist nur, dass wenn ich dort wo die UART Ausgaben gemacht 
werden, probiere ein anderes File zu öffnen, dies nicht zu funktionieren 
scheint da er wohl immernoch etwas in der Fat struct am rumschreiben ist 
und ffopen ja schliesslich auch auf diese zugreift ?

Was mir gerade vorhin aufgefallen ist, dass die ffls Funktion mir die 
Dateien mehrmals ausgibt wenns mehr als nur ein paar auf der Karte hat.
z.b. habe ich 3 Ordner gemacht und er hat mir diese 3 Ordner einige Male 
aufgelistet und dazwischen immer Punkte ausgegeben z.b. wie folgt

ORDNER1
ORDNER2
ORDNER3
.
.
..
..
.
ORDNER1
ORDNER2
ORDNER3
.
.
..
..
.

etc.

von Torsten S. (tse)


Lesenswert?

1) In eine Codesammlung gehört fertiger, funktionsfähiger Code. Sagt ja 
der Name schon.

2) Gute Programmierkenntnisse der verwendeten Sprache sind dafür 
zwingend erforderlich.(#include "fat-0.3.c")

3) Es gibt bereits (erprobte) Libs hier in dieser Codesammlung die 
SD/MMC + FAT unterstützen. Wozu das Rad neu erfinden?

von Daniel R. (zerrome)


Lesenswert?

hallo,

@ Torsten S.

sieh mal in meinen ersten post, 4. zeile...

#include "fat-0.3.c" funktioniert doch oder? übersichtlicher ist das 
auslagern von prototypen in *.h dateien auf jeden fall nicht !
c standart ist, dass jede datei auch einzelnd compilierbar sein soll. 
ist doch so auch gegeben.

warum das rad neu erfinden? weil ich mein eigenes rad will! zudem hat ja 
wohl selber machen noch den größten lerneffekt. so wie theorie und 
praxis halt !

@  kalhou

schick mir ein image von der karte und dem von dir verwendeten code, 
dann kann ich dir genau sagen woran es liegt. sonst must bischen selber 
probieren. bei mir läuft es, das einzige problem sind mit linux 
formatierte karten, weil die komischerweise das root dir, wenn es nur 1 
cluster groß ist mit 0x0ffffff8 als ende markiert haben...
und dachte es ist eindeutig, man kann IMMER nur eine datei zum 
lesen/schreiben/anhängen öffnen! man kann aber durchaus mehrere 
nacheinander öffnen usw...

von Torsten S. (tse)


Lesenswert?

Daniel Platte wrote:

> warum das rad neu erfinden? weil ich mein eigenes rad will! zudem hat ja
> wohl selber machen noch den größten lerneffekt. so wie theorie und
> praxis halt !

OK. Warum nicht. Aber bitte erst wenns fertig ist in die Codesammlung.

> #include "fat-0.3.c" funktioniert doch oder? übersichtlicher ist das
> auslagern von prototypen in *.h dateien auf jeden fall nicht !

Ein großer Fehler, diplomatisch ausgedrückt. Sei froh, das noch keiner 
von den C-Experten seinen Senf dazugegeben hat.

Bitte meine Posting nicht als rumnörgeln betrachten, sondern als 
konstruktive Kritik um Dich auf den "richtigen" Weg zu bringen.

Torsten

von Daniel R. (zerrome)


Lesenswert?

hm,

meiner meinung nach ist der code schon durchaus brauchbar. vielleicht im 
falschen forum, mag sein. dann möge es bitte jemand verschieben.

bei der letzten version mmc-0.3.zip läuft bei mir mit verschieden 
formatierungen und cluster größen alles gut.

warum sind *.h dateien denn so wichtig? bzw der richtige weg (hatte es 
ja auch schon geändert..)?

bin offen für verbesserungen und anregungen, ist ja der sinn weshalb der 
code hier öffentlich rumsteht :)

güße daniel

von kalhou (Gast)


Lesenswert?

Könnte ich Morgen mal machen..
hab den code allerdings ein wenig abgeändert. Man sollte allerdings 
rausfinden was es ist. Zu dem Prototypen: Hab es auch so gelernt, dass 
man die Prototypen in das Headerfile auslagert und im zugehörigen c File 
dann einfach das Headerfile dazunimmt. Was wirklich richtig ist weiss 
ich auch nicht. Vielmehr stört micht, das wenn ich in einem c File z.b. 
strings.h benutze und im main-File dann eine Funktion aus diesem c File 
aufrufen will ich dann nochmals strings.h includen muss.

von Kevin K. (kalhou)


Angehängte Dateien:

Lesenswert?

Hier ist mein Beispielcode!

Habe gewisse Anpassungen an den Libraries vorgenommen z.b. die Struktur 
für Fat und File im Headerfile definiert etc. aber der Code sollte 
allgemein verständlich sein.

Auf der SD Karte hatte ich lediglich 3 Ordner (ORDNER1,2,3). Die Karte 
ist eine 1GB SanDisk und ist mit FAT32 formatiert.

Der Code wurde im AVRStudio compiliert, daher stammt auch das Makefile, 
welches noch im Ordner enthalten ist.



Gruss

[EDIT]
hab gerade gesehen, dass die Karte mit FAT16 mit Vista formatiert war. 
Hab sie dann FAT32 formatiert und ging gleich. Allerdings bleibt mein 
Problem das ich während der Funktion ffls(); statt der UART Ausgabe eine 
Datei und dann den Namen der aktuellen Datei dort reinschreiben will ;)

von Daniel R. (zerrome)


Lesenswert?

hallo,

werd mir deinen code und den fehler bei fat16-ffls mal ansehen, 
allerdings leider erst sonntag. bin übers wochenende weg..

grüße daniel

von Daniel R. (zerrome)


Lesenswert?

hallo,
hab mir den code angesehen, läuft bei mir problemlos. schade das du kein 
image von der karte gemacht hast, mit der es nicht ging. so ist der 
fehler für mich nicht reproduzierbar.
zu deinem problem, was du möchtes ist eine datei suchen um dann etwas 
damit zu machen oder?

wenn ja:
die funktion ffopen gibt 0 zurück wenn die datei die du lesen/anhängen 
willst in dem aktuellen verzeichniss vorhanden ist. wenn 0 zurück kommt, 
ist die datei auch schon fürs lesen oder anhängen "vorbereitet", also 
mit ffread() / ffwrite() zugänglich. kommt 1 bei ffopen('w',dateiName") 
zurück ist die datei vorhanden und muss gelöscht werden vor dem 
schreiben.

wenn nein:
hab ich keine ahnung was du machen willst ;)
dann erkläre es mal...

grundsätzlich sollten die datei-operation funktionen in file-0.x.c nur 
extern genutzt werden, da so sicher gestellt ist, das alle flags und 
structs richtig geladen/gesetzt sind. das war nämlich das problem bei 
dem was du wolltest...
z.b. wenn man file.name benutzen will aber dann ffopen aufruft, läd 
ffopen was neues auf file.name, weil ffopen eben auch ein dir auf eine 
datei durchsucht, und alles mögiche auf file.name landet bevor man das 
hat was man will...

grüße daniel

von Kevin K. (kalhou)


Lesenswert?

genau gesagt möchte ich alle files eines ordner auslesen und statt dann 
die filenamen über usart auszugeben, würde ich gerne den filenamen in 
eine liste eintragen, die dann etwa so aussieht

"
DATEI1  MP3; Interpret1; Titel1
DATEI2  MP3; Interpret2; Titel2
DATEI3  MP3; Interpret3; Titel3
DATEI4  MP3; Interpret4; Titel4
"

das ganze wäre z.b. in einer txt datei eingetragen: Also soll er 
eigentlich jedes File in dieser Form in eine Liste eintragen (ID3 Tag 
Erkennung habe ich schon gemacht)

wenn ich mehrere Files offen haben könnte wäre das ja kein Problem, da 
aber die Funktion lsRowsOfClust() selbst auf die File/Fat Struktur 
zugreifft gibt es ein Problem solange ich nur eine Datei offen haben 
kann.
Was mir in diesem Zusammenhang aufgefallen ist: Du hast ja anfänglich 
gesagt du würdest kein Support für mehrere Files die offen sind 
anbieten, da damit möglichst wenig Ressourcen gebraucht werden, 
allerdings sieht es so aus als wäre in fat-0.x.c eine statische Variable
1
extern unsigned char   sector[512];
 vorhanden die immer 512bytes Platz wegnimmt, ob man nun eine Datei 
offen hat, oder nicht..

von Daniel R. (zerrome)


Lesenswert?

hallo,

wieso willst du so eine datei anlegen? ist doch doppelt, weil es diese 
struktur doch eigentlich schon in dem ordner gibt...
man könnte das ganze so erweitern, dass id3 tags ausgelesen werden und 
mit angezeit werden, anstatt z.b. die länge der datei.

ps: hab grade getestet, läuft auch problemlos auf atmegas die nur 1kB 
ram haben.

von Daniel R. (Gast)


Lesenswert?

Hallo,
kann man mit der Lib auch formatieren?

von Daniel R. (zerrome)


Lesenswert?

hallo,

nein kann man nicht und wird man auch erstmal nicht.

von G.K. (Gast)


Lesenswert?

Daniel Platte (zerrome)

Danke für Deine Beiträge in Groß-/Kleinschreibung.

von gast (Gast)


Lesenswert?

> Danke für Deine Beiträge in Groß-/Kleinschreibung.

Da klemmen noch mehr Tasten. Beispiel:
1
*(unsigned char*)vi++=*bytesOfSec++;

von Siegmar (Gast)


Lesenswert?

"sUpEr Kommentare"

von JoJo (Gast)


Lesenswert?

Warum fehlen in so vielen Libs die Formatier-Routinen?
Sind die so aufwendig?
Kann doch jedes Handy/Kamera außerdem erspart man sich
damit die "Kompatibilitätsprobleme" mit Windows etc.

von Daniel R. (zerrome)


Lesenswert?

hm,

hab mir ehrlich gesagt noch nie gedanken darum gemacht eine formatier 
routine zu schreiben, wäre sicher nicht besonders schwer. gut, bei 
gelegenheit mach ich das mal :)

groß/kleinschreibung ist einfach nur nervig. ich schreibe außerdem sehr 
viel jeden tag, da bin ich froh wenn ich mal meine kleinen finger etwas 
schonen kann (die betätigen shift bei 10 finger tippen).


1
*(unsigned char*)vi++=*bytesOfSec++;

mit einem gecasteten void pointer byteweise auf 4 byte große variablen 
zu schreiben ist bis jetzt noch die eleganteste lösung meiner meinung 
nach...

güße daniel

von Joachim (Gast)


Lesenswert?

> Warum fehlen in so vielen Libs die Formatier-Routinen?
> Sind die so aufwendig?

Man muss für jede Kartenkapazität die passenden Werte (Clustergröße 
etc.) festlegen. Windows benutzt hierzu noch aus den alten DOS-Zeiten 
entstandene Werte. Nimmt man willkürlich andere Kombinationen, kann es 
Kompatibilitätsprobleme mit Windows geben. Deshalb ist es besser, gleich 
auf einem PC zu formatieren.
Außerdem sind alle SD-Karten werkseitig mit FAT16/32 vorformatiert.

> Kann doch jedes Handy/Kamera

Handy und Kameras können viel. Zum Beispiel auch nette Bildchen und 
Menüs auf Displays anzeigen.
Ist aber kein Problem. Gib einem Mikrocontrollerfreak 0,01 Cent für 
jedes je verkaufte Handy oder jede Kamera, und er wird Dir jede 
erdenkliche Funktion in der Lib implementieren ;-)
Ich selbst habe z.B. noch nie eine Karte in einer Kamera formatiert.
Wozu soll das gut sein? (Fotografiere sehr viel mit Canon EOS 20D)

> außerdem erspart man sich damit die "Kompatibilitätsprobleme" mit Windows etc.

Wenn man selbst formatiert und nicht alles genau richtig macht, fangen 
die Kompatibilitätsprobleme mit Windows etc. erst an!


Joachim

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

hallo,

hier nochmal eine etwas verbesserte version.
bug in run_cmd behoben.
benchmark teil kann mit #define benchmark 0 oder 1 ein oder aus 
geschaltet werden.

grüße daniel

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

bug beim leere datei lesen beseitigt.

so das wäre es dann erstmal.

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

hallo,

die neuste version ist erweitert um:

ffmkdir - legt verzeichniss in aktuellem verzeichniss an.
ffrm    - kann jetzt auch ordner löschen. löscht rekursiv !

in der fat-0.3.h ist ein define :

#define smallFatSys  1

wird es auf

#define smallFatSys  0

gesetzt, dann passt der code in einen atmega8 , mit schreib und lese 
unterstüzung und kommando prompt !

falls jemand fehler findet, bitte melden !

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

bugfix in ffrm...

von Timo (Gast)


Lesenswert?

Hallo Daniel,

erst einmal Danke für die Arbeit die du dir machst.

Allerdings habe ich noch ein Problem:
(Vorneweg: Ich benutze die Version 0.3.1 und den CodeVisionAVR-Compiler.
 Ich habe also den Code an einigen Stellen angepasst. Dies betraf in den
 meisten Fällen jedoch nur Variablendeklaration u.ä..)

Also:
Ich erstelle eine Datei mit
1
temp = ffopen('w',dateiim8.3format);
, was auch wunderbar funktioniert.
Nun möchte ich an diese Datei jeweils verschiedene Daten (Strings) 
anhängen
(z.B. Datum  Uhrzeit  ...) und die TXT-Datei später im PC auslesen.
1
temp = ffopen('a',dateiim8.3format);
2
ffwrite('irgendeinzeichen');
3
...
4
ffclose;

Das funktioniert auch noch, allerdings nur bis die Datei eine Größe von 
512Byte überschreitet. Lese ich nun die Datei im PC aus, sehe ich nur 
die Zeichen, die auf den neuen Sektor geschrieben wurden.
Dies ist bei allen Vielfachen von 512 der Fall. (Also bei jedem neuen 
Sektor?)
Nun würde mich mal interessieren, ob das ein allgemeiner Fehler ist oder 
ob ich beim Anpassen an CodeVision einen Fehler gemacht habe.
Wenn das der Fall ist, wäre ich für Tips dankbar, wo ich zu suchen habe. 
;)

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

hallo,

ja danke. dicker bug in ffwrite und was blödes in ffopen.


ist geändert !

och als arbeit würde ich das nicht umbedingt bezeichnen ;) macht doch 
spass

von Timo (Gast)


Lesenswert?

Ok, schon mal Danke fürs Ändern.
Mit meinem CodeVision bekomme ich nun leider in so fern Probleme, das 
beim Linken die Fehlermeldung: "Error(s) occured" during assembly." 
erscheint. Könntest du mir sagen, an welchen Funktionen Du für die 
Version 0.4.2 etwas geändert hast, damit ich nicht alles noch mal 
portieren muss?!

also in ffopen, ffwrite & fat_setCluster hab ich schon was gefunden..

schon mal vielen Dank...

von Lolipop E. (lolipoper)


Lesenswert?

Mir ist nun mein ForumPW wieder eingefallen, deswegen nicht mehr Timo, 
sondern nun LoLiPoPer.
Ich habe nun einfach noch mal die komplette Version 0.4.2 nach CV 
portiert.

Jetzt klappt es schon besser. Aber es läuft noch nicht ganz rund.
Jetzt steht in der Datei, die ich wie oben beschrieben anlege, der erste 
Teil (die ersten 512 Bytes) drin, dann ist eine Pause von 512 Byte(nur 
Leerzeichen)und ab hier gibt es noch kleine Fehler jeweils wenn die 
Vielfachen von 512Bytes erreicht werden.
Kleine Fehler in so fern, dass immer ein paar Zeichen verloren gehen.
Das ganze sieht in der TXT in etwa so aus:


<----512Byte----><----512Byte----><----512Byte----><----512Byte----><--- 
--...
"text text text ""               ""text text tex"    "text text t"
                         |                         |                |
                   große Lücke                kleine Lücke     kl. Lücke

Wenn du da noch mal schauen könntest, wäre das klasse..
Macht ja Spaß ;)

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

hallo,

eben erst zurück gekommen...

da ist wohl noch eine variable falsch gesetzt gewesen.
danke für deine mithlife und geduld. bin selbst die ganze zeit schon am 
bugs suchen, aber je mehr mitmachen umso besser wird es werden.

ist ein wenig umständlich hier nur den auszug zu posten, deshalb als 
anhang die geänderte file-0.3.c

geändert nur eine zeile in ffopen in dem teil:
1
   if(option=='a' && file_flag==0){
und zwar fehlte die angabe(nach zeile 94):
1
   cntSecOfClust=s+1;
die für ffwrite nötig ist, um zu wissen in welchem sektor des clusters 
man sich grade befindet. die berechnung ist da auch noch etwas 
umständlich, wie auch in ffseek...

von Lolipop E. (lolipoper)


Angehängte Dateien:

Lesenswert?

Servus..

bei der Menge an Code ist es ja ganz klar, dass man mal ne Kleinigkeit 
übersieht. Alles klein Problem..

Die von mir beschriebene "große Lücke" ist nun weg. Die kleinen gibt es 
allerdings immer noch.
Ich hänge als Anhang mal die Textdatei an, damit du dir selbst n Bild 
machen kannst.
In der Datei werden immer Datensätze in dieser Form:
#;NUMMER;DATUM;UHRZEIT;MESSWERT (für Import in Excel)
aneinandergereit. An einigen Stellen fehlen eben einige Daten.
(Wenn du die Datei mit Excel öffnest ist das auch ganz gut zu erkennen.)

Was mir noch aufgefallen ist:
Wenn ich mit ffopen('w',"DATEINAMTXT"); eine Datei anlegen will, diese 
jedoch schon existiert, bekommen ich von ffopen nicht immer den 
Rückgabewert 1 geliefert. d.h. die Datei wird neu angelegt und befindet 
sich dann zwei mal auf der SD-Karte. Die Inhalte sind jeweils die 
gleichen und es geht auch nix verloren. Schön is das aber nicht. ;)
Ab und zu ist der Rückgabewert aber korrekterweise auch 0.

So, das sollte erst mal genug sein.. ;)

von Daniel R. (zerrome)


Lesenswert?

hallo,

woher kommen die daten die auf die karten sollen denn? sind die auf 
jeden fall korrekt? werde morgen nochmal exzessiv testen mit großen 
datenmengen und hin und her kopieren von dateien usw...

hattest du die karte neu formatiert, als du den neuen code verwendet 
hattest?
wenn nicht könnten so sachen mit ffopen('w',"DATEINAMTXT"); passieren. 
werde ich mir morgen aber auch nochmal genau anschauen.

güße daniel

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

hallo,

kann die bugs nicht bestätigen. habe mehrere dateien mit w erstellt, mit 
a sachen angehangen in verschiedenen größe (vielfachache von 512 usw). 
läuft immer alles ok. kommen deine daten über den uart?

poste doch mal die funktionsaufrufe wie du sie machst. vielleicht werd 
ich daraus schlauer.

als anhang nochmal das aktuellste programm

von Lolipop E. (lolipoper)


Lesenswert?

hmm.. wenns bei dir so läuft, kann es ja eigentlich nur an mir liegen.

Ich poste mal die Funktionsaufrufe, evtl. ist ja dort ein Schnitzer 
drin.
Ansonsten kann es ja immer noch sein, dass beim Portieren nach CV was 
falsch gelaufen ist.

Vorweg: Die SD-Karte ist eine ScanDisk 512MB.
        Formatiert habe ich diese mit WindowsXP Prof. als FAT und auch 
mal
        als FAT32. (Ich formatiere die Karte auch bei ca. jedem 2. 
Versuch
        neu.)
Hier jetzt die Aufrufe:
1
// External Interrupt 6 service routine                                    
2
// Interrupt wird ausgelöst, wenn entweder die SD-Karte rausgezogen oder 
3
// eingesteckt wird. Entsprechend wird SD_ONLINE = 0 gesetzt oder die 
4
// Initialisierung durchgeführt und SD_ONLINE = 1 gesetzt.
5
interrupt [EXT_INT6] void ext_int6_isr(void)
6
{  
7
  char temp;
8
  delay_ms(500);    //Warten, bis Karte richtig ein- / ausgesteckt
9
  if(((SD_Detect)==0)&&(SD_WriteProtect==0)){
10
        puts1(SDKartegefunden);
11
        
12
        puts1(SDInit);
13
        temp = mmc_init();              
14
        if(temp==0){
15
                puts1(OK);     
16
                puts1(FATInit);
17
                temp = fat_initfat();                  
18
                if(temp==0){
19
                        puts1(OK);
20
        
21
                        puts1(messdatatxterstellen);
22
                        temp = DV_MESSDATATXTerstellen();
23
                        if(temp==0)puts1(OK);
24
                        else puts1(Dateibereitsvorhanden); 
25
                        
26
                        SD_ONLINE = 1;
27
                        }    
28
                 else puts1(Fehler);
29
        }
30
        else puts1(Fehler);
31
  }      
32
  else {
33
    puts1(SDKartenichtgefunden);
34
    SD_ONLINE = 0;
35
    }
36
}
dazu die Funktion DV_MESSDATATXTerstellen();
1
char DV_MESSDATATXTerstellen(){
2
        char temp=0;                            
3
        temp = ffopen('w',messdatatxt);
4
        if(temp==1) return(1);                  //Datei existiert bereits             
5
        do{   
6
                ffwrite(messdatatext[temp]);
7
                temp++;
8
        }
9
        while(messdatatext[temp]!='\0');        
10
        ffclose();
11
        return(0);   
12
        }
Diese Funktion wird in der mainloop jede Sekunde aufgerufen:
1
char DV_MessungSpeichern(int Nummer){
2
        char temp;
3
        char TEMP[4]="   ";  
4
        unsigned long int Abstand; 
5
        unsigned char Abstand_ASCII[32];
6
        #asm("cli");
7
        
8
        itoa(Nummer,TEMP);
9
        
10
        temp = ffopen('a',messdatatxt);
11
        if(temp==1) return(1);                  //Datei nicht vorhanden
12
       
13
        ffwrite('#');                           //Zeilenführungszeichen 
14
        ffwrite(';');      
15
        
16
        ffwrite(TEMP[0]); 
17
        ffwrite(TEMP[1]); 
18
        ffwrite(TEMP[2]);
19
        ffwrite(';');     
20
        
21
        ffwrite(Tag_ASCII[0]);
22
        ffwrite(Tag_ASCII[1]);
23
        ffwrite('.');       
24
        ffwrite(Monat_ASCII[0]);
25
        ffwrite(Monat_ASCII[1]);
26
        ffwrite('.');         
27
        ffwrite(Jahr_ASCII[0]);
28
        ffwrite(Jahr_ASCII[1]);
29
        ffwrite(Jahr_ASCII[2]);
30
        ffwrite(Jahr_ASCII[3]);
31
        ffwrite(';');        
32
        
33
        ffwrite(Stunde_ASCII[0]);
34
        ffwrite(Stunde_ASCII[1]);
35
        ffwrite(':');  
36
        ffwrite(Minute_ASCII[0]);
37
        ffwrite(Minute_ASCII[1]);
38
        ffwrite(';');  
39
        ffwrite(';');      
40
        
41
        ffwrite('\n');
42
        ffwrite('\r');
43
        ffclose();  
44
        
45
        #asm("sei"); 
46
        MessungNr++;
47
        return(0);   
48
        }
Die Variablen Sekunde_ASCII, usw. sind globale Variablen, die aus einem 
RTC-Chip stammen. Die Variablen gebe ich im mainloop jeweils zur 
Kontrolle per UART aus.(Da stimmen die Daten immer.)
messdatatxt ist ein globaler String:char* messdatatxt="MESSDATATXT";

Ich hab jetzt noch mal rumprobiert. Folgende Fehler treten auf:
- Ein Datenblock 512Byte fehlt ganz(kommt sehr selten vor).
- Einige Datensätze fehlen teilweise.
- MESSDATA.TXT wird mehrfach erstellt

Hoffentlich hab ich hier was falsch gemacht. Sonst wirds ungemütlich..

von Daniel R. (zerrome)


Lesenswert?

hallo,

also die karte sollte nur dann abgezogen werden, wenn ganz sicher keine 
schreib/anhäng operation gemacht wird. also besser einen pin mit 
schalter versehen und erst nachdem der schalter gedrückt wurden und 
sicher ist, dass die karte nichts mehr macht raus ziehen. oder irgnedwie 
anders sicher stellen, dass keine operation läuft während man den strom 
wegnimmt.

grundsätzlich sieht dein code ok aus. benutzt du die letzte version der 
lib?

habe mit:
 fat32 und 4 sektoren pro cluster
 fat16 und 1 sektor   pro cluster
 fat16 und 4 sektoren pro cluster,
getestet. hab über das programm dateien auf die karte geschrieben, 
angehangen, ausgelesen usw. alles ohne probleme.
kannst du evtl. noch fat und file *.c dateien posten, dann schau ich mir 
mal die änderungen dort an.

hast du ein delay in der main, um DV_MessungSpeichern aufzurufen, oder 
mit timer?

güße daniel

von Lolipop E. (lolipoper)


Angehängte Dateien:

Lesenswert?

moin moin...

jipp, den Taster hab ich drin. Bevor ich die Karte abziehe setze ich 
über einen Taster SD_ONLINE = 0; und DV_MessungSpeichern(); kann nur bei 
SD_ONLINE ==1; aufgerufen werden.
1
 if(SD_ONLINE){ 
2
        temp = DV_MessungSpeichern(MessungNr);
3
        }

Ich hab jetzt mal etwas umprogrammiert. Und zwar beim EXTINT6 mit 
einigem Erfolg:
1
// SD-Card initialisation // FAT-File System initialisation
2
if(((SD_Detect)==0)&&(SD_WriteProtect==0)){
3
        puts1(SDKartegefunden);       
4
        puts1(SDInit);
5
        temp = mmc_init();              
6
        if(temp==0){
7
                puts1(OK);
8
        
9
                puts1(FATInit);
10
                temp = fat_initfat();                  
11
                if(temp==0){
12
                        puts1(OK);
13
                        puts1(messdatatxterstellen);
14
                        temp = ffopen('r',messdatatxt);
15
                        ffclose();
16
                        if(temp==1){
17
                          DV_MESSDATATXTerstellen();
18
                          puts1(OK);
19
                          SD_ONLINE = 1;  
20
                          }           
21
                        else puts1(Dateibereitsvorhanden); 
22
                        }    
23
                 else puts1(Fehler);
24
                 }
25
        else puts1(Fehler);
26
        }
27
else puts1(SDKartenichtgefunden);
sprich: Ich mache die Abfrage, ob eine Datei schon vorhanden ist, indem 
ich versuche sie zu lesen.
Was merkwürdig ist: Auch wenn die Datei vorhanden ist, liefert 
ffopen('r',..); anscheinend immer 1 zurück.
Damit wird DV_MESSDATATXTerstellen(); jedesmal ausgeführt. ABER:
Es bleibt bei EINER Datei!! (verstehe im mom nicht wirklich warum, aber 
das Ergebnis ist das Erwünschte!)
Das Problem reduziert somit auf einen einzigen Fehler:
Wenn ich weniger als 1024Bytes in eine TXT-Datei schreibe klappt alles 
wunderbar. SChreibe ich jedoch mehr als 1024Byte in die Datei fehlen die 
2. 512Bytes (bzw sind diese mit Nullen(Leerzeichen) aufgefüllt). Danach 
ist wieder alles OK.

DIe Lib ist die 0.4.2!

Ahja, und DV_MessungSpeichern(); wird nach einem delay aufgerufen.
(Das auch nur zur Probe. Später soll das dann per Taster laufen.)

Im Anhang sind noch die File.c & die FAT.c. Allerdings in einer 
TXT-Datei, da ich den Code erst mal einfach in die MAIN.c geknallt habe.

Hoffe, du musst nich zu viel Aufwand betreiben..
ALso schon mal Danke..

von Daniel R. (zerrome)


Lesenswert?

hallo,

ich kanns nicht sehen, aber du sorgst doch dafür, dass bei programmstart 
file_flag mit 0 initialisiert wird(ein ffclose macht das auch..)? es 
gibt nämlich nur 3 möglichkeiten warum ffopen('r',datname); 1 zurück 
gibt.

1. wenn file_flag nicht 0 ist.
2. wenn die datei nicht im aktuellen verzeichniss gefunden wurde.
3. wenn das laden des 1. sektors der datei fehl schlägt.

ich habe in der option bei ffopen im write teil etwas geändert, 
erscheint mir sicherer, änder das auch noch grad.
1
if(option=='w' && file_flag==0){  
2
   if(1==fat_loadFileDataFromDir(name)){
3
   ...
4
   ...
5
   ...
6
   return(0);
7
   }
8
}

warum bei daten größer 1024 dieser bug bei dir auftritt ist mir grad 
noch ein rätsel, schau ich mir aber noch genau an.

nach dem delay hatte ich nur gefragt, um sicher sein zu können, dass da 
kein interrupt irgendwo reinpfuscht :)

für mich wäre noch interessant, wieviele sektoren pro cluster hat die 
karte mit fat32 formatiert? wenn du das so grad nicht nachsehen kannst, 
mach einfach mal sowas nach der fat init:
1
char tmp[12];
2
ultoa(fat.secPerClust,tmp,10);
3
uputs("secPerClust: ");
4
uputs(tmp);


ach was mir grad noch einfällt, wie ist die karte an den avr 
angeschlossen?
da können auch mal ein paar bytes verloren gehen wenn die kabel zu lang 
oder so. bin selber jetzt auch auf einen 74hc4050 umgestiegen um die 
karte zuverlässiger anzuschließen (kostet 40 cent).

grüße daniel

von Lolipop E. (lolipoper)


Lesenswert?

Mal wieder Hallo!;)

Das file_flag hatte ich nicht expliziet mit 0 initialisiert. Ich dachte, 
sowas läuft über die Initialisierung von fat_initfat();
Probiert hab ich das jetzt aber mal (auch mit ffclose(); beim 
Programmstart), bringt aber keine Änderung.

Den Teil in ffopen hab ich aktualisiert.

Am Anschluss der Karte kann es eigentlich nicht liegen, da ich das 
"Savvy128"-Board von chip45.com verwende.

Interrupt verwende ich schon, allerdings schalte ich die bei jedem 
Zugriff auf die Karte mit #asm('cli');  aus.
(Ext. Interrupt vom RTC-Chip)

Deinen Code zur Sektorenbestimmung liefert bei FAT32 den Wert "8" und 
bei FAT den Wert "16".

hmm.. mit dem Umweg über ffopen('r',..); zur Dateienerstellung kann ich 
leben, nur das Löschen der Daten wenn ich mehr als 1024 Byte schreibe 
stört schon.

von Daniel R. (zerrome)


Lesenswert?

also,

nach nochmaligem debugen kann ich einen fehler da aussließen.
wichtig ist einfach nur die reihenfolge:

1. ffopen
2. ffwrite/ffread
3. ffclose

dann kann da nix schief gehen. irgendwo fehlt warscheinlich eine 
kleinigkteit in deinem code, irgend eine änderung die ich gemacht habe, 
die du aber nicht gemacht hast. probier mal einfach so in einem test 
programm, die funktionalität der fat-lib (neuste version mmc-0.4.3.zip). 
so kommst du vielleicht auf den fehler.
hab auch nicht deinen ganzen code um mir das mal anzusehen.
z.b. hast du
1
unsigned char ffwrite(unsigned char c){
2
   unsigned long int clusterOld;
3
   clusterOld=currentCluster;
4
   ...
5
   ...
das so geändert. da wird beim schreiben von einem byte immer direkt auch 
eine unnötige long int operation gemacht (4 byte operation), das ist 
ungünstig.

die von dir beschriebene lücke klingt für mich so, als wenn da ffclose 
irgendwo falsch aufgerufen wird.

grüße daniel

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

hallo,

als anhang mal eine ganz einfache nutzung der lib.
erstellt eine datei, schreibt daten rein und hängt daten an.
erstellt einen ordner und erstellt die datei nochmal darin.

grüße daniel

von Kai F. (kai-) Benutzerseite


Lesenswert?

Hallo,
saubere Arbeit!
Vielleicht wäre es bald übersichtlicher einen wiki Artikel zu schreiben, 
wo auch Minimal und Optimalschaltplan drin sind und immer die neuste 
Version drin steht. Eine SD Lib für Codevision wäre super, poste also 
bitte mal den Code sobald er läuft.
Viel Spaß noch

Kai

von Daniel R. (zerrome)


Lesenswert?

hallo,

@ Lolipop Er
wie siehts denn jetzt aus bei dir? läuft es oder nicht?
wenn es dir nichts ausmacht, poste doch auch mal so eine mini version 
mit den änderungen für codevision. falls das noch nicht läuft, können ja 
vielleicht auch andere mal mitschauen.

@  Kai Franke
zum thema wiki, hab ich noch nie gemacht. interesse scheint auch nicht 
allzu groß zu sein. übersichtilicher wäre es allerdings schon ;)

grüße daniel

von Lolipop E. (lolipoper)


Lesenswert?

hey Daniel,

jetzt rennt er!! ;)
Ich habe noch mal die Version 0.4.3 neu portiert. Anscheinend war die 
Kleinigkeit, die Du da geändert hast ausschlaggebend.

Bevor ich das online stelle, möchte ich noch mal ein bisle mit den 
Ordneroperationen rumspielen um zu sehen ob das auch fehlerfrei 
funktioniert.
Und alles n bisle ordentlich machen. (also *.c - & *.h files erstellen.)

Müsste ich bis heut Abend hinbekommen.

bis dann..

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

hallo,

äh ja, ordner operationen da gibt es noch was... tritt selten auf, aber 
hier der bugfix, sorry.

muss man denn viel ändern zu codevision? ist doch auch ein standart c 
compiler, oder?

von Kai F. (kai-) Benutzerseite


Lesenswert?

Da ich bis zum 15. meinen Artikel für den Artikelwettbewerb fertig haben 
muss, werde ich wohl bis dahin auch wissen wie man einen wiki Artikel 
erstellt und biete an auch für diesen Artikel einen zu erstellen.
Ich sage dann nochmal Bescheid, dann könnt ihr mir ja beide eure 
Errungenschaften schicken und ich vereine sie im wiki.
Editieren und hinzufügen wird ja jeder hinbekommen :P

Gruß
Kai

von Lolipop E. (lolipoper)


Angehängte Dateien:

Lesenswert?

Soo..
denn stelle ich mal den Code online.

So viel ist nicht zu ändern für CV. Hauptsächlich die 
Variablendeklarationen. Ist aber schon immer etwas Aufwand.
Aber nun hab ichs noch mal mit der V0.4.4 gemacht. (Allerdings hab ich 
die Funktionen nicht noch mal sauber formatiert.)
Wenn da noch irgendwo was zukommt, änder ichs auch gern noch mal.(Wäre 
natürlich schöner, wenn ich wüßte in welchem Teil was geändert wurde, 
dann muss ich nicht alles neu machen.)

Der Code wurde auch nicht in irgendeiner Weise extrem optimiert. Wichtig 
war mir in erster Linie, dass alles einwandfrei funktioniert und das 
ist, soweit ich weiß, auch gegeben.

@Daniel:
Wenn Fehler gemeldet werden, wäre es klasse, wenn du da mit nachschauen 
könntest und ich übernehme die Änderungen für CV.

von Daniel R. (zerrome)


Lesenswert?

hallo,

@ Kai Franke

fänd ich super, wenn du daraus einen wiki artikel machen würdest. ich 
schreibe gerne ein paar allgemeine sachen zur fat oder auch speziell zu 
dem code oder so...

@ Lolipop Er

werde die änderungen die ich jetzt ab version 0.4.4 mache in den dateien 
dokumentieren. angepeilt ist so ab version 0.5.x dass die statische 
variable sector[512] dynamisch übergeben wird. so könnte man, wenn das 
programm grade nicht den fat teil nutzt, 512 bytes ram sparen.
werde mir später mal deine umsetzung ansehen.

grüße und danke für die aktive teilnahme

daniel

von Florian (Gast)


Lesenswert?

Hi.
Leider funktioniert das schreiben nicht bei mir.
Er hängt sich immer bei ffopen auf...

Was ist da los?

Gruß Flo

von Daniel R. (zerrome)


Lesenswert?

hallo,
seltsam, also die initialisierung klappt?
was benutzt du für eine karte und wie ist die karte angeschlossen?
wie lautet der genaue aufruf von ffopen, also mit welchen parametern 
usw.

du benutzt die aktuelle version (mmc-0.4.4.zip)?

grüße daniel

von Florian (Gast)


Lesenswert?

Ich benutze version 0.4.4.
Habe den ATMega128.
Die SD karte ist am Hardware SPI interface angeschlossen.
ffopen gibt 1 zurück.

//********************************************************************** 
*******************************************
int main(void){

  lcd_init();
  lcd_string("Computer start",0);

  RoteLED();

  set_cursor(0, 3);
  lcd_string("0%",0);


  //----------sd-karte initialisieren----------
  if(mmc_init() !=0)
  {
    lcd_clear();
    lcd_string("Keine SD-Karte ist eingesteckt.",0);
    while(1);
  }
  //----------sd-karte initialisieren----------



  set_cursor(0, 2);
  for(int i=0;i<16;i++)
  {
    lcd_data(0xff);
    _delay_ms(10);
  }



  set_cursor(0, 3);
  lcd_string("100%",0);

  _delay_ms(1000);
  lcd_clear();



  //----------fat initialisieren----------
  if(fat_initfat()!=0)
  {
    lcd_clear();
    lcd_string("Fat konnte nicht gelesen werden!",0);
    while(1);
  }
  //----------fat initialisieren----------


  lcd_string("FAT-16 gelesen",0);




  if(ffopen('w',"DELME   TXT")==1)
  {
    lcd_clear();
    lcd_string("File konnte nicht angelegt werden!",0);
    while(1);
  }

    //2
  unsigned char str[22]="das soll auf die karte";
  unsigned char i=0;

    //3
  do{

     ffwrite(str[i]);
     i++;
  }while(str[i]!='\0');

  //4
  ffclose();



  set_cursor(0, 2);
  lcd_string("Fertig",0);

  while(1);

  return 0;
}

Ist da was falsch?

Gruß Flo

von Daniel R. (zerrome)


Lesenswert?

hm,
ffopen mit option 'w' gibt auch 1 zurück wenn die datei schon vorhanden 
ist.
versuch mal ein
1
ffrm("DELME   TXT");

vor dem öffnen mit ffopen. das würde die datei löschen für den fall das 
sie da ist.
sieht sonst richtig aus...

von Daniel R. (zerrome)


Lesenswert?

ach was ich grad sehe,
der code von dir ist teilweise aus einem blöden beispiel...
der string str[22] müsste 23 zeichen lang sein, weil
"das soll auf die karte" sind 22 zeichen.

von Florian (Gast)


Lesenswert?

Also habe den Code nun geändert.
Jetzt geht das Programm glatt durch (ohne Fehlermeldungen).
Doch auf dem PC wird keine datei angezeigt. (Auch im Hex-editor sehe ich 
keine neuen einträge!)
Irgendwas stimmt da nicht...

Gruß Flo

von Daniel R. (zerrome)


Lesenswert?

hm

das ist mal komisch. ist die karte vielleicht partitioniert? dann muss 
man das umstellen auf:

#define superfloppy  0

in der fat-0.4.h

standartmäßig ist das so eingestellt, das die karte unpartitioniert ist.

würde erklären warum der pc keine daten sieht, aber die initialisierung 
der karte am mc durchläuft und auch geschrieben werden kann. bei 
fat_initfat() wird nicht auf sinnigkeit der ausgelesenen daten geprüft. 
ergo landen die daten an merkwürdigen stellen der karte, weil die 
bereiche der fat falsch ausgelesen werden...

von Florian (Gast)


Lesenswert?

JUHUHUHU es klappt.
Genau der Fehler war es... ^

Einfach #define superfloppy  auf 0 stellen und ich kann lesen und 
schreiben!!

Vielen Dank.
Gruß Flo

von Daniel R. (zerrome)


Lesenswert?

hallo,

schön das es klappt. muss mir mal überlegen wie ich erkennen kann ob im 
sektor 0 ein mbr steht oder der erste sektor der fat, dann könnte man 
das automatisieren...

grüße daniel

von Daniel R. (zerrome)


Lesenswert?

ein neues update.
die änderungen sind in den *.c dateien dokumentiert.
änderungen nur in der fat-0.4.c und file-0.4.c.

grüße daniel

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

äh hier auch noch die dateien...

von Alex (Gast)


Lesenswert?

Hallo,

mich würde interessieren ob ihr auch solche Probleme mit dem Compiler 
habt in AVR-Studio. Mit jedem Fehlermeldung die ich beseitige, 
erscheinen 10 andere. Das ist ja nichts besonderes :D aber irgendwann 
war ich mit meinem Latein am Ende...

Hat einer von euch eine fehlerfreie AVR-Studio version?

lg alex

von Alex (Gast)


Lesenswert?

Ich nochmal,

das Problem mit den mit AVR-Studio lag wohl am Projekt an sich. Nach 
einem Computer-Neustart und eines neuen Projekts hat das compiling 
fehlerfrei funktioniert.

Bei meinem ATmega88 bedeutet das mit -0s Program: 7498 bytes (91.5% 
Full)
mit smallFileSys 0.

Habe noch zwei Fragen:

1. Wie wirkt sich smallFileSys auf den Funktionsumfang aus?

2. Gibt es ein switch für NUR Schreibzugriff? Bzw. welche Funktionen 
kann ich weglassen um mehr Programmspeicher zu haben.

lg alex

von Daniel R. (zerrome)


Lesenswert?

hallo,

bei "smallFileSys 0" fällt das löschen von dateien und das rekursive 
löschen von ordnern weg, das anlegen von ordnern und das wechseln in 
einen höheren ordner auch ("cd.." quasi). der rest ist dabei.

einen schalter um nur schreib bzw lese zugriffe zu machen hatte ich auch 
schon vor. werd ich auch die tage noch machen. das problem dabei ist, 
dass einige funktionen die zum lesen gebraucht werden auch zum schreiben 
gebraucht werden, ich kann grad nicht so abschätzen wieviel kleiner das 
wird. nur lesen wird man wohl auf weniger als 3 kByte bekommen.

bei mir gab -O2 den kleinsten code


gruß daniel

von Daniel R. (zerrome)


Lesenswert?

also,

ich bekomme eine nur lesen version auf 3618 bytes code gedrückt, ohne 
weitere optimierungen und ohne tolle ff-funktionen wie ffseek usw.
eine nur schreiben variante wird aber nicht viel kleiner werden können 
als 5990 bytes an code. das liegt daran, dass man ja auf jeden fall auch 
das dateisystem lesen muss um schreiben zu können...
will man ein verzeichniss wechseln können, muss der ganze lese kram mit 
rein...
möchte man nur einen daten logger bauen, so wird wohl ein atmega88 oder 
8 mit 8 kBytes flash reichen, will man da mehr, braucht mann mehr flash.

grüße daniel

von Alex (Gast)


Lesenswert?

Hallo,

das hört sich ja sehr gut an :D

Ich bin an der nur schreiben variante interessiert, wäre nett wenn du 
das mal bei gelegenheit zu verfügung stellst.

viele Grüße alex

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

hallo,

sorry hat etwas gedauert...
die änderungen sind nicht wild...

avr-size main_.hex
mit den schaltern (nur schreiben ohne große datei funktionen) :
1
#define smallFileSys 0  
2
#define write 0

gibt nach dem kompilieren 6538 bytes an code an. sind doch 500 mehr, 
weil ich übersehen hatte das man beim schreiben auf jeden fall auch noch 
ffseek braucht.

mit den schaltern (komplette unterstützung):
1
#define smallFileSys 1
2
#define write 0

wird der code 8228 bytes groß.

mit den schaltern (minimal system, nur lesend):
1
#define smallFileSys 1
2
#define write 1

wird der code 3618 bytes groß.


güße daniel

von Thomas (Gast)


Lesenswert?

Hallo!

Danke für die Bibliothek!
Insgesamt laufen die Funktionen ganz gut. Mit 2 Sachen habe ich jedoch 
noch einige Probleme:

1. Die Funktion ffopen('w', ...) braucht bestimmt 10 Sekunden um zu 
Entscheiden, dass die Datei nicht vorhanden ist, und eine neue angelegt 
werden muss. Ist das normal? ffopen('a', ...) braucht nämlich nur wenige 
ms.

2. Die Funktion ffopen('a', ...), bzw. das zugehörige ffclose schließt 
die Datei nicht korrekt, sodass sie anschließend am PC (oder MAC) mit 
1,32 GB Größe angezeigt wird. Eine Idee, wodran das liegen könnte? 
(Atmega 2560 mit 2GB SD und 64MB MMC Karte).

MfG Thomas

von Daniel R. (zerrome)


Lesenswert?

hallo,

-1 nein das ist alles andere als normal. es sei denn man möchte eine 
datei in einem ordner anlegen in dem es schon sehr sehr viele 
dateien/ordner gibt.

-2 poste doch mal eine funktionsaufrufe damit ich mir ein bild davon 
machen kann woran es liegt.

wie sind die karten formatiert, also mit fat32 oder fat16? mit welchem 
betriebssystem sind die karten formatiert worden? hast du sie vor der 
benutzung der lib neu formatiert?

klingt ein bischen so als würde fat_loadFileDataFromDir irgendwie ne 
macke haben, weil alle drei optionen/funktionen diese funktion nutzen, 
also ffopen (w/a) und ffclose auch, wenn mit ffopen(a) geöffnet war...
schau ich mir mal genauer an...

von Thomas (Gast)


Lesenswert?

Hey,

der ganze Aufruf sieht in etwa so aus:
1
if( mmc_init() == 0 )
2
{
3
    if(0 == fat_initfat())
4
    {
5
            //Fat initialisation successful
6
            LCD1.LCDBuffer[1] = 0 + 48;
7
            printLCDBufferToGraphic(1);
8
9
            unsigned char j = 0;
10
            unsigned char datei[12]="TEST    PTL";
11
12
            // neu erstellen wenn nicht vorhanden und reinscheiben
13
            if(ffopen('w',datei) == 1)
14
            {
15
                ffopen('a',datei);
16
            }
17
            for(j=0;j<5;j++)
18
            {
19
              ffwrite('b');
20
            }
21
            ffclose();
22
    }
23
}

Ich benutze die KArten mit FAT16, mit FAT32 funktioniert es nicht. 
Formatiert mit Windows, jedoch formatiere ich die Karten nicht nach 
jedem Versuch neu. (Ist ja eigentlich auch nicht der Sinn der Sache)

Einstellung für:
1
#define superfloppy  0
2
#define smallFileSys 1

Ansonsten arbeite ich mit Version 0.4.4, da die Änderung zu 0.4.5 nicht 
groß genug schienen. Habe relativ viel an den Header Dateien geändert, 
um sie schön einzubinden. (Von wegen - wer darf was sehen, und warum / 
warum nicht) - komme von Java, und da ist das alles etwas schöner.

von Daniel R. (zerrome)


Lesenswert?

hm,

die header dateien sind relativ egal denke ich.

es kann sein das wegen der partition irgendwo ein bug ist. versuch mal 
die karte unpartitioniert zu benutzen, dass sollte auf jeden fall 
problemlos funktionieren.

ich komme erst später heute abend zum testen...
ich gehe mal davon aus das nur die header dateien geändert wurden, falls 
nicht, müsste ich mal den ganzen code sehen.

güße daniel

von Daniel R. (zerrome)


Lesenswert?

hallo,

es gab keine bugs in dem partitions bereich, hätte mich sonst vorher mal 
gemeldet.

hier trozdem mal eine neue version, ist schneller geworden, aber auch 
etwas gefährlicher ;)

es ist jetzt umbedingt erforderlich zu prüfen ob richtig geöffnet wurde 
bevor man schreibt !
ein beispiel:

1
// neu erstellen wenn nicht vorhanden und reinscheiben
2
if(0==ffopen('w',datei)){      // prüfen ob öffnen erfolgreich
3
   for(z=0;z<60000;z++){  
4
      ffwrite('a');    
5
      }  
6
   ffclose();
7
   }

nur wenn ffopen null zurück gibt wird ffwrite aufgerufen. ffwrite prüft 
nicht mehr ob öffnen erfolgreich war. zudem ist ffwrite und ffread 
inline geworden.
code ist allgemein kleiner geworden durch vielfache optimierungen !

durchschnittswerte mit einem atmega168 @ 16 mhz:

165 kByte lesend
146 kByte schreibend

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

...

von Daniel R. (zerrome)


Lesenswert?

hier mal noch der erste wiki versuch...

http://www.mikrocontroller.net/articles/FAT32

werde da noch weiter daran arbeiten. jeder der zu fat etwas beitragen 
kann/möchte ist eingeladen dort mitzuarbeiten...

grüße daniel

von Alex (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Daniel
Ich finde deinen  Quelltext für die SD-Karte eine gute Idee. Habe 
allerdings aber auch meine Probleme damit.
Ich verwende:
AVR-Studio
ATmega32
mmc-0.3.1.zip
Mein Problem:
Trotz intensiver Fehlersuche habe ich es bis jetzt nicht schaffen können 
ein Hexfile mit deinem Quelltext zu erstellen. Habe die 0.3.1 Version 
genommen weil dort auch die Routine für ein LCD dabei ist.  Ich bekommen 
immer Fehlermeldungen. Habe deinen Quelltext nicht verändert. Die 
Fehlermeldungen habe ich in den Anhang gepackt. Wäre nett wenn du oder 
jemand anderes sie mal anschauen könnte. Weiß gerade nicht mehr weiter, 
ist bestimmt nur ein dummer Fehler aber steh da jetzt auf dem Schlauch.
Gruß Alex

von Daniel R. (zerrome)


Lesenswert?

hallo,

ja hm das avr-studio...
hab da letztens auch mal die dateien kompilieren wollen, ging aber 
nicht. irgendwie löst das die c abhänigkeiten nicht alleine?!?. am 
einfachsten ist es wenn du das makefile das bei meiner lib babei ist 
benutzt. beim avr-studio kann man in den projekt eigenschaften ein 
externes makefile angeben. dann gehts. außerdem ist dringend davon 
abzuraten eine ältere version als 0.4.5 zu nutzen (besser 4.5.6), da 
doch noch einige fehler in den vorherigen versionen waren.
um ein lcd zu nutzen, könntest du einfach die lcd routinen mit 
übernehmen...

güße daniel

von Alex (Gast)


Lesenswert?

Danke

Werde ich gleich mal ausprobieren.
Gruß Alex

von holger (Gast)


Lesenswert?

In file-0.4.h

>extern unsigned char ffmkdir(char name[]);    // legt ordner in >aktuellem 
verzeichniss an.
>
>#include "file-0.4.c"

So etwas tut man nicht! *.c Dateien sollte man nicht per
#include einfügen.

von Daniel R. (zerrome)


Lesenswert?

also über das makefile oder wie?

bist du Holger Klabunde?

von Alex (Gast)


Angehängte Dateien:

Lesenswert?

Naja zumindest habe ich jetzt nicht mehr so viele Fehlermeldungen aber. 
Aber er erstellt mir kein Hexfile. Woran kann das denn liegen?

Hab mal mein ganzes Prog angefügt vieleicht weißt du ja Rat.
(alles Unveränderte Dateien von dir)

Danke für deine Bemühungen

Gruß Alex

von Daniel R. (zerrome)


Lesenswert?

hallo,

hab grad kein windows da um avr-studio zu starten. aber ich meine mich 
zu erinnern, dass ein projekt und die haupt c datei gleich heißen 
müssen. also solltest du ein projekt namens main_ erstellen und da dann 
alle dateien einfügen...

gruß daniel

von Alex (Gast)


Lesenswert?

Ne hat leider auch nicht funktioniert.

Trotzdem danke
Versuche noch ein bischen rum wenn ich ne Lösung finde poste ich die.

Alex

von zerrome (Gast)


Angehängte Dateien:

Lesenswert?

probier mal das hier. wenn das nicht geht ist dein avr-studio schrott

von zerrome (Gast)


Lesenswert?

hm,
nee seh grad mit meinem avr-studio projekt kann das auch nicht gehn, 
weil der pfad zu den dateien nicht stimmt und der pfad zum kompiler 
warscheinlich auch nicht.
na ja was auf jeden fall geht ist ein neues projekt mit namen main_ zu 
erstellen, dann avr-studio schließen und die dateien main_.c usw in das 
projekt verzeichniss kopieren, dort die vom avr-studio erstellte datei 
main_.c überschreiben. dann das studio wieder starten. eventuell noch 
das externe makefile einstellen.

von Alex (Gast)


Lesenswert?

So hab noch lange rumprobiert aber leider keinen Erfolg gehabt.
Mit der Version 0.4.6 lässt sich kein Hex File erstellen.
Jedoch mit der Version 0.3.1 ist dies kein Problem.
Wieso das so ist weiß ich nicht und kann ich mir auch schlecht erklären.
Hab die AVR Progs extra neu runtergeladen und neu installiert, sogar auf 
anderen PC´s probiert. Leider alles ohne erfolg vielleicht hat ja jemand 
anders noch nen Rat. Würde ja gerne wissen was das Problem genau ist.

Gruß Alex

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

hab jetzt mal die header dateien so umgebaut wie die portierbarkeit wohl 
am größten ist.
leider zu lasten der ausführungsgeschwindigkeit. alleine durch die 
header dateien gehen 20KBytes pro sekunde lesend 
verloren...seltsamerweise wird der code kleiner aber auch langsamer...

@ Alex
probier mal die neue version, damit sollte es besser klappen.
ich denke es liegt nicht am code der 0.4.6 sondern am einbinden im 
avr-studio, daher könnte es mit der 0.4.7 einfacher sein.

grüße daniel

von holger (Gast)


Lesenswert?

Die wenigsten werden WinAVR unter /opt/cross installiert haben ;)

CC = /opt/cross/bin/avr-gcc
OBJCOPY = /opt/cross/bin/avr-objcopy
OBJDUMP = /opt/cross/bin/avr-objdump
SIZE = /opt/cross/bin/avr-size
NM = /opt/cross/bin/avr-nm

von Steffen (Gast)


Lesenswert?

hmmm... 20kB/s weniger ist schon interessant. Wahrscheinlich konnte der 
Compiler bei deiner ersten Version (wo er ja alles in einer einzigen 
Datei bekommt) besser optimieren durch z. B. Inlining (was den größeren 
Code erklärt).

Durch die Aufteilung ist es jetzt allerdings besser in die Verwaltung 
von IDEs wie dem AVRStudio einzubeziehen.

Btw. Super Sache, dass du deinen Code zur Verfügung stellst.

Steffen.

von Alex (Gast)


Lesenswert?

hab das Makefile mal umgeschrieben und volgendes verändert

# Define programs and commands.
SHELL = sh
CC = /WinAVR/bin/avr-gcc
#OBJCOPY = /WinAVR/bin/avr-objcopy
#OBJDUMP = /WinAVR/bin/avr-objdump
#SIZE = /WinAVR/bin/avr-size
#NM = /WinAVR/bin/avr-nm
AVRDUDE = avrdude
REMOVE = rm -f
COPY = cp

so kriege ich auch ein hexfile erstellt aber ob das jetzt auf dem atmega 
läuft werde ich dann später erst sehn. Oder könnte es sein das es ohne 
die auskommentierten Pfade nur so scheint als sollte es Funktionieren? 
Warte noch auf den uc momentan hab ich leider keinen da.
Danke für eure Hilfe.

Gruß Alex

von zerrome (Gast)


Lesenswert?

geht das nicht auch so?

# Define programs and commands.
SHELL = cmd.exe
CC = /WinAVR/bin/avr-gcc.exe
OBJCOPY = /WinAVR/bin/avr-objcopy.exe
OBJDUMP = /WinAVR/bin/avr-objdump.exe
SIZE = /WinAVR/bin/avr-size.exe
NM = /WinAVR/bin/avr-nm.exe
AVRDUDE = avrdude.exe
REMOVE = del -f
COPY = copy


bei "del -f" bin ich mir nicht sicher ob del den parameter f kennt, 
warscheinlich nicht, da müsste man mal nach adequatem ersatz suchen.
"rm -f" -> "Löschen. Ignorieren nicht vorhandener Dateien, keine 
Nachfragen."

copy müsste aber so gehn gehn..

grüße daniel

von Daniel R. (zerrome)


Lesenswert?

lol moment bei windows wird das warscheinlich eher

c:\WinAVR\bin\avr-gcc.exe heißen...

mit optimierung s wird der code jetzt wieder kleiner als mit 2 und der 
geschwindigkeitsverlust geht auf 10KBytes /sec zurück. also von 165 auf 
155KB damit kann ich leben (atmega 168 @ 16mhz).

von Steffen (Gast)


Lesenswert?

Der Pfad zu Winavr wird doch in die Path-Variable eingetragen, sollte es 
nicht reichen die *.exe anzugeben? Er wird sich dann schon einen Pfad 
suchen...

Hab es nicht probiert!

Steffen.

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

neue version

kleine änderungen.
mit windows und linux makefiles usw..

von Michael Z. (incunabulum)


Lesenswert?

Moin Daniel,

wollte mich heute auch mal näher mit deinem SD-Code beschäftigen, 
nachdem meine Platine ansonsten funktioniert. Die Funktionsweise sieht 
verständlich aus.

Was mich momentan am Einsatz hindert ist, dass SPI, Usart wie auch die 
Command-Shell fest mit dem eigentlichen Code verbunden ist. Da ich 
hierfür bereits eigene Bibliotheken habe.... wie kann ich diese auf 
Dauer am besten einbinden und zwar so, dass der Wartungsaufwand bei 
einer Codeaktualisierung deinerseits nicht zu umständlich wird?

Oder hast du schon einmal überlegt, die ganzen relevanten #defines in 
eine Config.h auszulagern. Hierin könnten z. B. Methodennamen für Usart 
und SPI definiert sein oder auch, ob file.h->methode() auf den Usart 
ausgeben soll.... Und diese Datei wäre dann problemlos anpassbar durch 
einen anderen Anwender.

Anders gefragt - wenn ich dir einen entsprechenden Patch schicke würde, 
hättest du Interesse?

cu, Michael

von Michael Z. (incunabulum)


Angehängte Dateien:

Lesenswert?

Ich nochmal.... anbei als zip eine kleine Abwandlung deiner Lib mit 
einem globalem Config-Header-File. Es kompiliert; ausprobiert habe ich 
es aber nicht.

Zur Idee: In mmc_defs.h werden für uart, spi und spi hardware die 
entsprechenden Methodennamen als #define angegeben. Beispiel Uart:
1
#include "uart.h"
2
#define MMC_UART_INIT      uinit
3
#define MMC_UART_PUTC      uputc
4
#define MMC_UART_PUTS      uputs
5
#define MMC_UART_GETC      ugetc
6
#define MMC_UART_GETS      ugets

Möchte ich einen anderen Uart-Code verwenden, so include ich die 
entsprechende Header-Datei und passe die Methodennamen an.
- ugets wird z. Zt. nicht verwendet.
- Die SPI Methoden sollte man nochmal überdenken... da wollte ich dein 
Feedback abwarten bevor ich deinen Code vollständig verstehen will

Somit kann ich flexibel unterschiedliche Basisfunktionen für die 
Peripherieansteuerung verwenden (buffered, unbuffered usart; hardware 
spi, software spi; evtl. debug Lösungen) und bin deutlich flexibler, was 
die gesamte Konfigurierbarkeit anbetrifft. Die restlichen Code-Dateieen 
enthalten jetzt nur noch die SD-Card-Logik allein.

Was hälst du davon?

Michael

von Daniel R. (zerrome)


Lesenswert?

hallo Michael,

gute idee das so zu ändern, dass man unterschiedliche "unterbauten" 
nehmen kann, würde es auch einfacher machen das ganze auf andere 
controller zu portieren.
eine globale "hardware" header datei zu machen, wo die funktionen vom 
spi und die funktionen des uart, also der hardware anbindung der karte 
und der ausgabe, definiert werden ist eine gute lösung. die von dir 
beschriebenen vorteile sind es wert.

leider komme ich vor freitag wohl kaum zur umsetzung, weil ich umziehe 
und lernen mich voll in beschlag nimmt.

bis spätestens sonntag sollte es aber ohne probleme drin sein, wie im 
einzelnen, werde ich mir noch überlegen. weitere ideen sind sehr 
willkommen !

grüße daniel

von Michael Z. (incunabulum)


Angehängte Dateien:

Lesenswert?

Moin Daniel,
Das klingt ja sehr schön :-) Wenn du Zeit hast, dann schau dir meine 
Abwandlung mal an... vielleicht sind ja ein paar brauchbare Ideen drin.

Eine "globale" Hardware-header-Datei würde ich zuerst mal auf die 
mmc-lib beschränken. Warum? Viele dürften für die Ansteuerung der 
peripherie etc. bereits eigene Code-Sammlungen haben. Die mmc-lib müsste 
dann nur noch an diese Libs angedockt werden.

Die SPI Ports und Pins könnte man auch nochmal in eine weitere 
Config-Datei auslagern. So habe ich es jedenfalls bei mir gemacht, siehe 
Attachement SpiDefs.h

Zweite Idee: Ein Debug-Switch. Ist dieser gesetzt, so wird an eine 
ebenfalls frei definierbare Debug-Funktion die aktuelle Aktion (open 
file, read directory etc.) gesendet. Sowas kann man schön so 
programmieren:

#define MMC_DEBUG 0

#if defined(MMC_DEBUG)
  logDebug("bla");
#endif

Anyway, denn erstmal viel Erfolg beim Lernen und Umziehen....

Michael

von Steffen (Gast)


Lesenswert?

Hallo,

interessant wäre, wenn der SPI-Teil umgearbeitet wird, gleich zu 
überlegen, ob nicht eine "universellere" Variante erarbeitet wird. Ziel 
könnte sein, dass mehrere Komponenten am SPI (-Bus) hängen und nicht SS 
sondern ein Portpin für CS verwendet wird. Beim Senden und Empfangen 
muss dann zusätzlich noch mitgeliefert werden, welche SPI-Peripherie 
angesprochen werden soll (SPI-Parameter müssen für jeden Baustein 
gespeichert werden und evtl. vor dem Senden/Empfangen neu angepasst 
werden).

So könnte z.B. ein zusätzlicher CAN-Baustein oder HC595 angeschlossen 
werden ohne eine Software-SPI zu benötigen. Besonders, wenn einzelne 
SPI-Komponenten nur selten benötigt werden (Config.ini auf SD Karte nur 
zum Start notwendig, HC595 für Relaisansteuerung einmal pro Sekunde...).

Steffen.

von Michael Z. (incunabulum)


Lesenswert?

Moin!

Wieso sollte dies ein Problem sein?

In der MMC-Config kannst du imho frei definieren, welchen Pin du als 
SS-Pin verwenden willst. Ob dies nun der "offizielle" SS-Pin des AVRs 
oder ein anderer Pin ist spielt hierbei keine Rolle. Somit kannst du 
auch problemlos mehere SPI-Chips oder -Geräte an den AVR anschließen 
solange du die gleiche Ansteuerungslogik (send_byte etc.) verwendest.

Aufwändiger wird es allerdings, wenn du unterschiedliche 
Busgeschwindigkeiten fahren willst. Da hast du recht.

Michael

von Steffen (Gast)


Lesenswert?

>Aufwändiger wird es allerdings, wenn du unterschiedliche
>Busgeschwindigkeiten fahren willst. Da hast du recht.

Genau dort sehe ich der Herausforderung. An der Stelle ist es 
wahrscheinlich sinnvoll "eine" SPI-Routine zu verwenden. Dann kann man 
sich merken, ob eine Parameteränderung durchgeführt werden muss oder 
nicht.

von holger (Gast)


Lesenswert?

>#define MMC_DEBUG 0
>
>#if defined(MMC_DEBUG)
>  logDebug("bla");
>#endif


Das geht auch noch eleganter.

In der Headerdatei:
1
#define MMC_DEBUG_SECTORS_READ
2
#define MMC_DEBUG_SECTORS_WRITE
3
4
#ifdef MMC_DEBUG_SECTORS_READ
5
 #define DEBUG_MMC_SECTORS_READ  printf
6
#else
7
 #define DEBUG_MMC_SECTORS_READ(...)
8
#endif
9
10
#ifdef MMC_DEBUG_SECTORS_WRITE
11
 #define DEBUG_MMC_SECTORS_WRITE  printf
12
#else
13
 #define DEBUG_MMC_SECTORS_WRITE(...)
14
#endif

Im C-Code:
1
...
2
 DEBUG_MMC_SECTORS_READ("RS %lu 0x%08lX\n",sector,sector);
3
...
4
5
...
6
 DEBUG_MMC_SECTORS_WRITE("WS %lu 0x%08X\n",sector,sector);
7
...

So kann man mehrere Debugausgaben einzeln gezielt ein und
ausschalten. Es wird eben nur das benutzt was man gerade
benötigt. Das was man nicht haben möchte einfach in der
Headerdatei auskommentieren:
1
//#define MMC_DEBUG_SECTORS_READ

Im C Code spart man sich dann auch das

#if defined(MMC_DEBUG)
 Ausgabe("text");
#endif

Die Debugausgabe benötigt nur eine Zeile Code statt drei.

MMC_DEBUG("text");

von Daniel R. (zerrome)


Lesenswert?

hallo,
leider hab ich doch extrem weniger zeit als ich dachte.
bugs würden geändert werden, aber mehr ist momentan nicht drin, sorry.
nächste woche hab ich wohl etwas mehr zeit, hoffe ich...

grüße daniel

von Andi (Gast)


Lesenswert?

Hi Forum,
ich hab das nun auch mal ausprobiert mit dem FAT-Treiber...
Das Init funktioniert noch einwandfrei - danach geht nicht mehr viel:
z.B. ffls() - da hängt er ziemlich lange in einer Schleife, der Grund 
ist, dass die Variable fat.dataDirSec bei mir auf -2 steht...
Wie ist das bei Euch?
Ich hab meine Karte unter Win mit FAT16 und FAT32 formatiert - jedesmal 
mit dem selben Ergebnis...
Habt Ihr eine Idee an was das liegen kann?
Die eine Karte ist eine MMC 512 MB von Transcend, bei der anderen Karte 
(Sandisk 2GB) steht in der FAT-Strukur nur Käse - liegt wohl an der 
Grösse...
Schon mal danke für Eure Tipps...
Andi

von daniel (Gast)


Lesenswert?

hallo,
ist die karte partitioniert?
wenn ja musst du #define superfloppy ändern (in der fat.h).
-2 ist auch ein komischer wert für einen unsigned long int...

grüße daniel

von Michael Z. (incunabulum)


Lesenswert?

Daniel,

hast du inzwischen ein bisschen Zeit gefunden, die Debug- und sonstigen 
Änderungen einzuarbeiten? Dann könnte ich meine selbstgestrickten Dinge 
verwerfen und zurück zu deinem Code wechseln :-)

Michael

von Daniel R. (zerrome)


Lesenswert?

hallo,
bin momentan bis oben hin zu mit arbeit...

ich hab auch die karten meist selber nur mit linux gedebugt,
da hatte ich mir auch eine kleine mmc.c und mmc.h geschrieben, der rest 
code ist platformunabhänig...
das ist die bequemste art den code zu testen.
zudem kann man mit programmen wie WinHex auch images von datenträger 
machen und so kann man sogar ganz ohne mmc karten code debugen und 
testen.
einfach immer eine mmc.c und mmc.h an die hardwaremäßige plattform 
anpassen, schon ist die lib portiert (sofern standart c darauf läuft).
daher tendiere ich momentan dazu die debug geschichte erst in den 
semesterferien mal anzusehen (wie gesagt, debug mit linux ich wesentlich 
komfortabler).
den rest, also die uart und die mmc/spi geschichte so umzubauen, dass 
andere bibliotheken genutzt werden können mach ich über weihnachten, als 
kleines present ;)
spass beiseite, da werd ich wohl endlich ein wenig zeit haben mich 
meinem hobby zu widmen...

grüße daniel

von Andi S. (laserandi)


Lesenswert?

Hi,
ich versuche gerade die Dateien aus mmc-0.4.8.zip unter Linux zu 
kompilieren. Das geht auch Problemlos, nur wenn ich den Schalter write 
auf 1 (read only) setze bekomme ich folgende Fehlermeldungen:
1
~/sd_test/main_.c:50: undefined reference to `ffmkdir'
2
~/sd_test/main_.c:53: undefined reference to `ffmkdir'
3
~/sd_test/main_.c:68: undefined reference to `ffwrite'
4
command.o: In function `run_cmd':
5
~/sd_test/command.c:94: undefined reference to `ffrm'
6
~/sd_test/command.c:101: undefined reference to `ffmkdir'
7
~/sd_test/command.c:149: undefined reference to `ffwrite'
8
make: *** [main_.elf] Fehler 1
Ist das ein Bug oder habe ich etwas übersehen.
Bei "read only" werden diese Funktionen natürlich nicht gebraucht, aber 
ich dachte der write Schalter berücksichtigt diese Option.

Danke
Andi

von Daniel R. (zerrome)


Lesenswert?

hallo,

besser spät als nie ^^

also, in der main_.c wird auf die schreib funktionen zugegriffen, 
genauso wie in der command.c . den schalter auf nur lesend setzen 
funktioniert nicht, wenn man dann doch auf die schreib funktionen 
zugreift.
in der bibliothek selber stimmt das soweit alles. wenn du nur lesen 
möchtest, musst du dir eine main schreiben und nur auf die lesen 
funktionen zugreifen...

grüße daniel

von Martin (Gast)


Lesenswert?

Hallo,

da ich BMPs auf meinem S65-Display ausgeben möchte, die auf der SD_Card 
liegen, wäre es für mich auch interessant direkt auf sector[] 
zuzugreifen.
Die Funktion ffread() ist dafür zu umständlich. Wie könnte man dies 
realisieren?

Güße Martin

von Daniel R. (zerrome)


Lesenswert?

Hallo,
also du könntest z.B. aus der fat.c direkt die Funktion:
1
unsigned char fat_loadSector(unsigned long int sec)

aufrufen. Als Parameter bekommt die Funktion den zu ladenden Sektor 
übergeben. Danach ist der Sektor auf sector[].
Setzt allerdings Voraus, dass du den Sektor kennst.
Wenn du damit BMP's lesen möchtest, muss du ja auch die folge Sektoren 
kennen. Deshalb ist die ffread etwas umständlicher. Im Regelfall, gibt 
es aber ja aber nur einen Index der erhöht wird und eine Abfrage... erst 
wenn man 512 Bytes gelesen hat wird es etwas umständlicher, wegen dem 
Problem der folge Sektoren.

Grüße Daniel

von Martin (Gast)


Lesenswert?

Hallo Daniel,

wenn ich Dich recht verstehe, habe ich die Datei *.BMP mit ffopen() zu 
öffnen. Der der erste Sector befindet sich nun in sector[]. Da die größe 
der Datei bekannt ist, kann man mit sec++ und fat_loadSector(sec) den 
nächsten Sector in den Buffer sector[] laden. Dies wiederholt man, bis 
die ganze Datei geladen ist und schließt die Datei mit ffclose().

P.S Danke für die schnelle Antwort

Gruß Martin

von Daniel R. (zerrome)


Lesenswert?

Also Prinzipiell schon,
aber es kann mehrere Sektoren in einem Cluster geben, diese Cluster 
können auch nicht aufeinanderfolgen. Deshalb muss man zwischendurch in 
der Fat nach dem folge Cluster suchen, diesen auf Sektoren umrechnen und 
dann weiter lesen...
Wenn Du das alles beachtest, bist Du genau bei dem was ffread macht.

Das Prinzip wie Fat funktioniert habe ich versucht im Wiki Artikel 
FAT32 zu erklären.

PS: Ist Dir ffread nicht schnell genug? Wieso willst Du da was selber 
machen?

Grüße Daniel

von Martin (Gast)


Lesenswert?

Hallo Daniel,

ich hatte am Anfang vermutet, dass ffread zu langsam sei. Inzwischen 
habe ich die Funktion aber benutzt und musste feststellen, das sie für 
den Bildaufbau schnell genug ist. Dieser dauert für die 176x132 Pixel 
(1Pixel=2Byte) ca. 1 Sekunde (gefühlt). Mit dieser Geschwindigkeit kann 
ich leben. Was mir aber noch Sorgen bereitet ist das Schreiben auf 
SD-Card. Dabei wird die FAT so verändert, dass  man die Dateien in 
Windows zwar noch angezeigt bekommt aber das Löschen wird verweigert.

Gruß Martin

von Daniel R. (zerrome)


Lesenswert?

Hi Martin,
das mit der 1 Sekunde ist seltsam wenn du mit 16 Mhz @ Avr arbeitest,
weil mit Deiner Angabe komm ich auf 371712 Bit, ist ja 46464 Byte/Bild, 
da sollte wesentlich mehr drin sein, oder hab ich mich verrechnet?

Zu dem Windows, welches benutzt Du? Vista?
Ich bin da nicht ganz Spezifikations-konform, weil normalerweise müsste 
man die Uhrzeit der Zugriffszeiten (erstellen/lesen...) richtig 
eintragen. Der Einfachheit halber schreib ich Nullen rein...
Hatte beim Testen aber dieses Problem auch nie.
Würde Vista ähnlich sehen, beim Datum 00-00-0000 nicht klar zukommen ^^

Güße Daniel

von Martin (Gast)


Lesenswert?

Hallo Daniel,

da ich mit 3,3V Versorgungsspannung arbeite, zwecks der einfacheren 
Anbindung von SD-Card und Display, läuft mein m32 nur mit 12MHz. Nachdem 
ich zwei Byte von SD-Card gelesen habe muß ich sie in ein Integer 
umwandeln und noch zum Display schicken, das kostet zusätzlich Zeit. 
Meine Zeitangabe ist auch nur eine grobe Schätzung, der Bereich ist 
irgendwo zwischen 0,5 und 1s.

Zur SD-Card:
Ich habe es mit XP und Linux getestet. Beide behaupten die Karten seinen 
schreibgeschützt. Das habe ich mit 3 unterschiedlichen Readern getestet, 
auf die richtige Einstellung des mechanischen Schreibschutz habe ich 
auch geachtet. Die Dateien die mit 'a' beschrieben wurden seien 1,5GB 
groß, das behauten beide BS, obwohl die Karten nur 256 bzw. 512MB groß 
sind. Als Software benutze ich Deine mmc-0.4.8. Hardwareprobleme kann 
ich zu 90% ausschliessen, da das Lesen einwandfrei funktioniert, das 
einmalige schreiben auch. Nur das anhängen von Daten an eine bestehende 
Datei produziert den Fehler.

Das Anhängen muß ich aber nochmal genau überprüfen, wenn mir weitere 
SD-Cards zu Verfügung stehen. Mit meiner letzten mache ich nur noch 
Lesetests.

Gruß Martin

von Daniel R. (zerrome)


Lesenswert?

Hallo,
nur um mal abzuklopfen,
Du hast den Code nicht geändert oder so und Du achtest darauf, dass 
ffclose() aufgerufen wurde bevor du den Strom von der Karte nimmst, bzw. 
diese aus der Halterung ziehst (beim schreiben, beim lesen egal).

Mich würde dann auch der Aufruf und so interessieren, um abschätzen zu 
können wo da vielleicht der Fehler liegt.
Hab den Code so in der 0.4.8 Version selber im Gebrauch und mit Datei 
Größen noch nie Probleme gehabt.

Grüße Daniel

von Martin (Gast)


Lesenswert?

Hallo Daniel,

ich habe Deine Version komplett übernommen und mit meinen Funktionen 
erweitert. So im nachhinein betrachtet kann ich aber das Abziehen der 
Stromversorgung bevor ein ffclose stattgefunden hat nicht ausschliesen. 
Das geht halt in der Softwareentwicklnugsphase nicht immer.

Ein reaktivieren der SD-Cards unter Windows blieb bis jetzt erfolglos, 
Windows meldet immer einen aktivierten Schreibschutz oder behauptet das 
die Datei text.txt ein Verzeichnis sei. Meine letzte Hoffnung ist nun 
Linux.

Ich könnte auch mal probieren, die Datei mit ffrm() zu löschen.

Gruß Martin

von Daniel R. (zerrome)


Lesenswert?

Hallo,
also auch beim Versuch die Karten zu Formatieren gibt es 
Fehlermeldungen?

Generell ist das sehr seltsam. Eigentlich geht Schreibschutz über 
Software nur mit einem bestimmten Kommando an die Karte, was aber auch 
nicht jede Karte unterstützt...

Einen Versuch die Datei mit ffrm() zu löschen ist es auf jeden Fall 
wert. Schlimmstenfalls bleibt ein bisschen Datenmüll in der Fat über. 
Sollte aber mit einem Scandisk Tool zu beheben sein.

Ich vermute, dass im Dateieintrag der Datei irgendwas steht was keinen 
Sinn macht. Hast Du einen Hex-Editor mit dem Du Dir die Rohdaten auf der 
Karte ansehen kannst? Davon ein Screenshot wäre super :)

Um soetwas zu verhindern, könnte man einen Taster anschließen, der einen 
Interrupt auslöst und ffclose() aufruft.

von Martin (Gast)


Lesenswert?

Hallo,

ich habe es nun mit Linux probiert, alles ohne Erfog. Fdisk und 
mkfs.msdos werden zwar augeführt (ohne Fehlermeldung) aber danach ist 
alles beim Alten. Die Dateien sind also noch vorhanden, selbst ein dd 
if=/dev/zerro of=/dev/sdb brachte keinen Erfolg. Es sieht für mich so 
aus, als ob der Speichercontroler auf der SD-Karte auf read only steht. 
Das Komische ist nur, dass es bei zwei unterschiedlichen SD-Cards 
aufgetreten ist.

Einen Hex-Editor habe ich natürlich, was genau soll ich Dir übermitteln?

Auf die Idee mit der Interruptroutiene bin ich auch schon gekommen, die 
wird mir aber nur was bringen, wenn das Programm in einer Endlosschleife 
fest sitzt. Bei einem Zugriff auf eine falsche Speicherstelle und der 
nachfolgende Sprung ins Nirvana wird mir die ISR die SD-Card nicht 
schützen können, weil sie wahrscheinlich nicht mehr ausgeführt wird.

Gruß Martin

von Daniel R. (zerrome)


Lesenswert?

Hi,
also das mit dem Sprung ins Nirvana versteh ich nicht. Wenn Du sagen wir 
mal konstant Daten wegspeicherst, und ein ffclose wird aufgerufen, wird 
halt nur die Datei ordentlich geschlossen, also die aktuelle Größe usw. 
geschrieben. Macht jedes Betriebssystem ähnlich...
Also Daten Direkt schreiben und den Fat und Datenbereich zum Schluss 
aktualisieren. Deshalb kann man bei Usb-Sticks die einfach so 
herausgezogen wurden (beim schreiben) die Daten meist recovern.

Da Du keinen Code gepostet hast, kann ich nicht genau sagen wo der 
Fehler eigentlich liegen kann... Rechne Dir das mal durch, wie oft man 
eine Zelle beschreiben kann und wie oft du Tatsächlich schreibst.

Interessant wäre für mich der Sektor des Ordners in dem der Dateieintrag 
steht.

Die einzige Möglichkeit eine Karte mit der Lib zu zerstören wird zu oft 
schreiben auf die Karte sein, dass ist definitiv sicher. Wäre aber auch 
mit einem großen Betriebssystem nicht anders !

Wenn Du mit Linux und mkfs keinen Erfolg beim Formatieren der Karten 
hast ist da was ganz anderes im argen.
Aber interessehalber, schick mir mal eine. Dann schau ich da nach. Das 
glaub ich nämlich irgendwie nicht, formatieren mit Linux und dann sind 
da noch Daten so lesbar?!?

Güße Daniel

von Martin (Gast)


Lesenswert?

Hallo,

die Screeshots sind noch in der Mache. Habe soeben feststellen müssen, 
dass WinHex keine Screenshots zulässt. Schicken kann ich Dir auch eine, 
ich habe schlieslich zwei Defekte. Ich bräuchte halt nur die Adresse.

Zum Nirvana:
Wenn der Prozessor eine falsche Speicherstelle liest und versucht den 
Befehl dann auszuführen, wird eine Exception ausgelöst, fals der Befehl 
nicht bekannt ist. Schlimmer ist es aber, wenn an dieser Stelle ein 
ausführbarer Befehl steht, der aber nichts mit dem Programm zu tun hat. 
Das kann den Programmcounter und den Stack verändern. Der Prozessor 
befindet sich dann in einem nicht definierten Zustand. Wenn jetzt ein 
Interrupt ausgelöst wird kann alles mögliche passieren, aber bestimmt 
etwas sinnfreies.

Nach dem Formatieren unter Linux habe ich auch ganz blöd aus der Wäsche 
geschaut, als ich die Dateien wieder gesehen habe. Der 
Fortschrittsbalken beim Formatieren unter Windows bewegt sich auch bis 
zum Ende und dann meldet Windows erst einen Fehler. Sinngemäss "Befehl 
konnte nicht zum Abschluß gebracht werden". Ich denke das war der 
verify.

Ich such mir jetzt einen besseren HexEditor und mache die Screenshots. 
Kannst Du einen empfehlen?

Gruß Martin

von Daniel R. (zerrome)


Lesenswert?

Also ich nehm auch immer winhex. Musste halt nen gesamt Screenshot 
machen...

Was hat der Prozessor mit der mmc/sd karte zu tun? Die ganze Geschichte 
kommuniziert ja über SPI, also AVR <-> mmc/sd Karte. Da hat keiner 
direkten Zugriff auf Stack oder so des anderen..

Schick mir ne Mail an zerrome aT gmail PunKt com, dann schick ich Dir 
meine Adresse.

Meinst du mit Daten gesehen, dass Du die Daten mit dem Hex-Editor 
gesehen hast? Wäre klar, weil Formatieren nur den Fat Bereich ändert, 
sonst müsste ja immer die Ganze Karte platt gemacht werden.

Grüße Daniel

von Martin (Gast)


Lesenswert?

Hi,

der Screenshot [Alt]+[Druck] bzw. nur [Druck] legt bei mir unter WinHex 
nichts in der Zwischenablage ab, also nichts mit cut and paste!

Der Prozessor arbeit doch wohl die Befehle ab, somit auch die, die für 
das lesen und schreiben auf SD-Card zuständig sind. Der Stack ist der 
letzte Speicherbereich im Ram. Dieser wird benutzt um  Daten, die einer 
Funktion übergeben werden sollen aufzunehmen, aber auch die 
Rücksprungadresse um wieder ins Hauptprogramm oder in die aufrufende 
Funktion zurückzukehren. Der Stackpointer enthält die letzte benutzte 
Adresse auf dem Stack.

Nachdem ich einen Dateibrowser geöffnet habe, hat mir dieser die Dateien 
und Verzeichnisse wieder angezeigt. Das sollte nach einer Formatierung 
eigentlich nicht so sein.top

Die Mail schreibe ich heute Abend.

Gruß Martin

von Daniel R. (zerrome)


Lesenswert?

Hallo,

jetzt versteh ich glaube ich endlich was Du mit dem Nirvana meinst...
Klar, nach der ISR nochmal ins normale Programm zu springen macht in dem 
Fall keinen Sinn. Da wäre dann in der ISR ein exit() oder so angebracht.

Wenn Du einen Screenshot vom gesamten Bildschirm machst wenn Winhex 
offen ist geht nichts in die Zwischenablage? Versuchs mal mit dem tool 
Printkey...

Grüße Daniel

von Martin (Gast)


Lesenswert?

Hallo Daniel,

ich bin nun so weit, dass mein "AVR-Portable" BMPs mit 24Bit Farbtiefe 
dank Deiner Lib lesen und auch auf dem Display des S65 anzeigen kann. 
Ein einfaches Spiel (Pong) habe ich auch schon am Laufen. Was ich nun 
gerne noch realisieren möchte, ist das Abspeichern von Spielständen. Nun 
zu meiner Frage:

Gibt es eine Möglichkeit mit ffread den Namen eines Spielers auszulesen 
um den Pointer auf die richtige Stelle hinter dem Namen zu positionieren 
und dann mit ffwrite den Spielstand zu speichern?

Gruß Martin

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ich glaube ich würde das an Deiner Stelle so machen,

ein struct anlegen mit Spielername, Score usw.
Für sagen wir, die Top 10.
Jetzt aus einer Datei die Daten auslesen und ins struct schreiben.
Wenn jetzt ein Spiel vorbei ist, einfach den Score überprüfen und wenn 
nötig einen aus den Top 10 rauswerfen und den aktuellen Spieler ins 
struct schreiben.
Zuletzt noch das aktualisierte struct wieder in die Datei schreiben.

Das Problem ist ja, dass man lese und schreib Vorgänge trennen muss, 
weil nur eine Datei zum schreiben oder lesen geöffnet werden kann. Wäre 
mit dem oben beschriebenen Beispiel kein Problem. Denkbar wären auch 
noch andere Möglichkeiten, solange man lesen und schreiben trennt...

Werde mir da mal was überlegen, weil es ja schon schick wäre, eine Datei 
zu öffnen und dann lesen und schreiben zu können... muss man halt 
bisschen aufpassen was man macht ^^
Das Problem ist ja nicht das überschreiben von alten Daten (da ändert 
sich ja nix am Datei Eintrag in FAT und Ordner), sondern wenn über das 
alte Datei Ende hinweg neu geschrieben wird. Da muss dann ne menge mehr 
gemacht werden...

Grüße Daniel

von Daniel R. (zerrome)


Lesenswert?

Hallo,
deine SD Karten sind angekommen. Die Controller darauf sind OK. Aber es 
sind massenhaft kaputte Sektoren. Zu viele. Ich vermute ja bei so billig 
Herstellern, dass die keine Algorithmen zum mappen von logischen auf 
physikalische Sektoren einbauen...
mkdosfs wirft in der Standart ausgabe (Konsole) keine Fehler, aber dmesg 
liefert die ganzen Fehler...
Die eine Karte kann man sogar an manchen stellen noch beschreiben, die 
andere weigert sich einfach.
Ist eindeutig kaputter Flash, weil die Controller sich noch 
ordnungsgemäß verhalten.

Bin gerade an einer neuen Version der Lib... die 0.5,
da wird es große Änderungen geben. Es wird dann auch möglich sein zu 
lesen und schreiben auf einer geöffneten Datei. Muss aber viel umbauen 
dafür...



Grüße Daniel

von Martin (Gast)


Lesenswert?

Hallo Daniel,

die SD-Cards kannst Du behalten, die brauche ich nicht mehr. Was aber 
komisch ist, sind die haufenweise def. Sektoren, denn die Teile wurden 
kaum benutzt.

Ich bin schon gespannt auf die neue Lib. und stelle mich gerne als 
Betatester zur Verfügung. (So lange ich noch SD-Cards zum Schießen habe 
;-) )

Gruß Martin

von Daniel R. (zerrome)


Lesenswert?

Hallo Martin,

wenn du magst kann ich die Karten auch zurück schicken, dann kannste Dir 
die vielleicht auch nochmal ansehen.
Mit Massenhaft kaputten Sektoren meinte ich, dass so bei 10 gemeckert 
wurde. Das ist schon viel, weil eine gute Karte normalerweise noch 
Reserven hat, die benutzt werden wenn wenn defekte entdeckt werden.
Es ist auf jeden Fall Vorsicht geboten bei Flash Speicher..

Die Lib ist jetzt soweit fertig. Bin am testen und Debuggen.
Es entfällt der Parameter beim öffnen einer Datei. Also 'w','r', und 'a' 
sind nun überflüssig.
Es wird entweder die vorhandene Datei geöffnet oder wenn nicht vorhanden 
eine erstellt. Diese kann man dann lesen und beschreiben.
Will man an eine Datei etwas anhängen, wird diese einfach geöffnet und 
mit ffseek(file.length) ans ende gespult. Dann einfach schreiben...
Dazu und zu anderen neuen Aspekten aber noch Code Beispiele.

Denke ich werde Sonntag die Version mmc-0.5 Posten können.

Grüße Daniel

von Daniel R. (zerrome)


Lesenswert?

Es gibt noch Probleme bei fragmentierten Fat-Tabellen. Wenn ich das in 
den Griff bekommen habe ists fertig  :)
Im Idealfall, wo die FAT unfragmentiert voliegt, kann man 256000 
Byte-Blöcke in einem Rutsch lesen. Sollte also auch alles schneller 
werden. Beim schreiben ähnlich...

von Martin (Gast)


Lesenswert?

Hallo Daniel,

wie gesagt, Du kannst die SD-Cards behalten. Ich denke die kannst Du in 
der Testphase ganz gut gebrauchen.

Das hört sich ja schon sehr vielversprechend an. Wie heisst es doch so 
schön:" Gut Ding will Weile haben!". In diesem Sinne wünsche ich Dir 
viel Spass und natürlich auch Erfolg.

Gruss Martin

von Daniel R. (zerrome)


Lesenswert?

Hallo,

also wenn ich teste, dann eh nur mit images von Karten, nie mit den 
Karten selber...
Wäre auch viel zu umständlich da immer neu zu Formatieren und Dateien 
drauf zu kopieren um auf einen definierten Zustand zu kommen. So is das 
ne Sache von 2 Sekunden...


Grüße Daniel


edit:

Man stelle sich vor, eine schleife läuft Amok und das über mehrere 
Sekunden/Minuten oder so -> defekte Karte...

von Martin (Gast)


Lesenswert?

Hallo Daniel,

das mit den Images von Karten habe ich nicht verstanden, wo laufen die 
den?

Klär mich auf!



Gruß Martin

von Daniel R. (zerrome)


Lesenswert?

Hallo,

also ich mache ein Image von einer Karte (z.B. mit winhex), also von 
allen Sektoren.
Dieses Image öffne ich in meinem c-Programm als Datei (c-Programm auf 
PC). Diese Datei hat ja die Struktur der Karte und kann somit genau so 
benutzt werden.
Jetzt braucht man nur noch eine angepasste mmc.c und schon kann man 
problemlos Testen, ohne Karten zu gefährden und bequem am PC.
Abschließende Tests mit realer Hardware kommen dann natürlich dazu, aber 
da geht es nicht mehr so darum ob der Code das macht was er soll...

Grüße Daniel

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Sooo,
ist fertig.

Ist gut geworden, schneller und kleiner...
Viel Spaß damit.
Werde morgen oder so mal das Wiki mit bisschen Doku undso füttern.

Wer den Link noch nicht kennt:

http://www.mikrocontroller.net/articles/FAT32



Grüße Daniel

von Matze A. (matzeapa)


Lesenswert?

Hi,

ich bin blutiger Anfänger, zumindest was SD-Karten angeht.
Deswegen auch nen Anfängerfrage :)

Wie beschalte ich denn so eine SD-Karte? Kann mir mal jemand nen 
Schaltplan hochladen? Wär total nett!

Gruß
Matze

von daniel (Gast)


Lesenswert?

Hallo,
hab grad keinen Schaltplan da.
Das Problem ist ja meistens, dass die Karte 3,3 V braucht und so ein MC 
meist mit 5 V läuft. Da muss man also Level shiften. Ich mache das immer 
mit nem HC4050, ist ein Digital IC, dass wenn man es mit 3,3 Volt 
betreibt auch 3,3 Volt an den Ausgängen hat. Ist aber bis 15 V Tolerant 
an den Eingängen.
Ein Eingang hängt mit einem Ausgang zusammen.
Geht glaub ich bis 20 Mhz Frequenz und kostet 20 Cent.
Den Ausgang der Karte kann man direkt an den MC machen, da 3,3 V reichen 
für logisch 1.

mc -> hc4050 -> karte  (für SCLK,DI,CS)

karte -> mc            (für DO)

Grüße Daniel

PS: hab da in der ffmkdir() etwas übersehen, also noch bisschen Vorsicht 
beim Ordner anlegen...fix kommt bald...

von Matze A. (matzeapa)


Lesenswert?

aller besten dank für die hilfee bei der beschaltung!

ich habe zwar keine ordner operationen vor, aber ich werde aufpassen :)

was den einstieg vielleicht für alle anfänger erleichern würde, wäre ein 
beispielprogramm, in dem die meisten / wichtigsten funktionen einmal 
durchlaufen werden (Datei erstellen und öffnen, daten hinein schreiben 
und anhängen, etc (natürlich auch für ordner)). ähnlich wie die 
libraries von fleury und seine testprogramme - muß aber nich soo 
ausführlich und allumspannend sein. ich denke, ein atmega8 hat jeder 
zuhause rumfliegen...

ich muß nämlich gestehen, daß die fülle von dateien und die auf den 
ersten blick recht kryptischen befehlsnamen einen echt abschrecken 
können :)

gruß,
matze

von daniel (Gast)


Lesenswert?

Ja kann ich verstehen,
sieht wahrscheinlich echt seltsam aus wenn man sich die fat.c oder so 
ansieht (und erst der ganze doku Text ^^)... habe da für mich möglichst 
sprechende und lange Namen genommen...

Letztendlich sollen ja für einen normalen Anwender nur die Funktionen 
aus der file.c sein. Wie ffopen, ffclose, ffseek, ffwrite usw...
Ah nicht zu vergessen noch zwei elementare Funktionen mmc_init und 
fat_initfat, sonst nur Funktionen aus file.c...

Mache morgen oder eher Dienstag so ein Mini Beispiel. Bin für Anregungen 
immer zu haben.
Wollte im Rahmen der Dokumentation auch noch eine Beschaltung von MMC/SD 
Karten (Schaltplan und Fotos) machen.
Leider fehlt mir momentan die Zeit um mich richtig aus zu leben in 
meinem Hobby ^^

Grüße Daniel

von Matze A. (matzeapa)


Lesenswert?

Das klingt doch gut. Ich muß nämlich für die Uni Messwerte auf eine 
SD-Karte bannen und deine Library ist goldwert. - aber einen kleinen 
Denkanstoß brauche ich wohl noch :)

Ich habe vielleicht auch gleich noch eine Anmerkung (bitte versteh mich 
nicht falsch, ich finde deine Arbeit klasse und ziehe den Hut!):
So wie ich das verstehe, kann die Funktion ffwrite nur ein einzelnes 
Zeichen auf die Karte schreiben. Für viele Anwendungen ist es aber 
häufig nötig gleich einen ganzen String zu schreiben. Man müßte also 
jeden "Buchstaben" einzeln anweisen.
Wäre es nicht pfiffiger einfach eine Funktion alla:
1
void ffwrites(const char *s )
2
{
3
    while (*s) 
4
      ffwrite(*s++);
5
}

zu schreiben bzw.in die file.c zu packen?!

gruß matze

von Martin (Gast)


Lesenswert?

Hallo Daniel,

ich habe die neue LIB in meine alten Programme eingebaut.
Alle funktionierten auf Anhieb. Zum intensieveren Testen
komme ich in den nächsten Tagen.

Tolle Arbeit, Danke dafür!

Gruß Martin

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

danke das ihr mit testet.

Die angesprochene Funktion ffwrites ist aufgenommen.
Zudem ist in der fat.c noch eine Funktion fat_str hinzu gekommen, die 
sonst immer woanders untergebracht war.
Mit dieser Funktion kann man einen String von "test.txt" in "TEST 
TXT" wandeln, so muss ja schließlich alles auf die karte...

Anbei sind jetzt, wie ich denke einfache Beispiele zur Benutzung der 
Lib, für einen atmega8. Der is leider ein bisschen zu klein für den 
vollen Umfang der Lib (z.B. Ordner Rekursiv löschen und anlegen).

Der Bug in ffmkdir ist behoben. Keine weiteren Bugs bekannt...

Was mich noch stört, ist die Tatsache, dass mehr als 100 KBytes 
schreiben möglich wären, aber durch einen blöden Vergleich von zwei 
unsigned long int (ist nötig wegen der überschreiben Funktionalität) nur 
80-85 KBytes geschrieben werden...
Muss mal sehen ob das nicht einfacher geht...

Grüße Daniel

von Matze A. (matzeapa)


Lesenswert?

Hi,

ich verzweifel langsam. ich komm einfach nicht durch die mmc_init.

ich denke, es liegt an meiner verkabelung. hier eine kleine ascii-skizze 
:)
(ATmega162)

--------\
09 (NC)  \
01 (CS)  | ---------- (PB1)
02 (DI)  | ---------- MOSI   (PB6)
03 (GND) | -------------------------- (-)
04 (VCC) | -------------------------- (+)
05 (CLK) | ---------- SCK    (PB7)
06 (GND) | -------------------------- (-)
07 (DO)  | ---------- MISO   (PB5)
08 (NC)  |
---------

Ich habe den ATmega162 mit 3,3V laufen, daher kein HC4050 dazwischen. 
Ich hoffe, daß ist soweit richtig und ich habe nur ein brett vorm kopf.
Als quellcode habe ich das beispiel von "mmc_0.5.1" genommen.

oder mache ich was falsch, wenn ich mein ISP kabel, das ja die selben 
ports benutzt, dranlasse?

ich komm echt nicht weiter und brauche wirklich hilfe!

gruß und danke, matze

von daniel (Gast)


Lesenswert?

Hi,


bist du sicher, das überhaupt das Programm drauf ist? Ist ISP nicht mit 
5 Volt? Sieht nämlich sonst Ok aus.

Wie lang sind die Kabel vom MC zur Karte?

Und ja, besser ISP Stecker abmachen.



Grüße Daniel

von Matze A. (matzeapa)


Lesenswert?

So, habe den fehler nach langem probieren gefunden. irgendwie hat der 
uart nicht geklappt, wenn der isp nicht angeschlossen war. ich habe 
jetzt als work-around einfach die masse, an der es lag, von PC zum uC 
extra gezogen.
jetzt geht alles.

aber wie zum kuckkuck mach ich nen zeilenumbruch?
ich hab schon alles probiert: \n und \r sogar schon den 0x0D (ascii code 
für zeilenumbruch).

hilfe.

danke,
matze

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Hallo,
schön das es jetzt klappt.

Zeilenumbruch wo? Im Terminal Programm?
Je nachdem welches du benutzt musst du das auf vt100 oder so 
umstellen... dann sollte uputc('\n') oder uputs("\n") auf jeden Fall 
gehen.

Anbei ein Funktionsübersichts Diagramm der ganzen Lib.
Krieg leider die Größe nicht in den Griff. Also hier die Warnung: 2412 x 
7946 Pixel :)

von Matze A. (matzeapa)


Lesenswert?

ne,  im terminalprogramm weiß ich das (ich mach das immer mit 0x0D). 
aber in der*.txt auf der SD karte.
Ich kriegs einfach nicht hin.

gruß
matze

von daniel (Gast)


Lesenswert?

Hallo,

also mein hex Editor sagt bei Windows Zeilenumbruch:

0x0D 0x0A für neue Zeile...

Das ist der Hex Code
1
746573740D0A7A65696C650D0A6E65750D0A
für
1
test
2
zeile
3
neu

Grüße Daniel

von Daniel R. (zerrome)


Lesenswert?

Update,
bei Linux ist ein Zeilenumbruch nur 0x0A...

von Chris (Gast)


Lesenswert?

Ich möchte jedemenge einfache Bytes in eine Textdatei schreiben. Das 
klappt auch alles gut, ich mache mir nur gedanken um die Lebensdauer der 
Karte.

Wäre es besser, wenn ich die Bytes nicht direkt mit ffwrite(byte); auf 
die Karte schreibe, sonderen erstmal in einem großen String speichere 
und diesen dann später komplett auf die Karte übertrage, oder macht das 
keinen unterschied?

Ich benutzte einen MEGA32, RAM wäre noch genug dar, um z.B. 512Bytes 
zupuffern.

von Daniel R. (zerrome)


Lesenswert?

Hallo,

nee das ist kein Problem, da ja schon 512 Bytes gepuffert werden.
Halt ein Sektor, bevor geschrieben wird.

Was allerdings schlecht wäre, ist nach dem schreiben immer direkt ein 
ffclose (obwohl man später eigentlich noch mehr schreiben will), weil 
dabei die Datei Daten ein Update erfahren. Dies bedeutet, dass einmal 
der Sektor wo der Dateieintrag drin steht neu geschrieben wird und evlt. 
muss auch die FAT geupdatet werden (wenn mehr Bytes geschrieben wurden 
als über Cluster schon verkettet sind). Und natürlich der Sektor in dem 
man gerade geschrieben hat auch.

Also einfach öffnen und dann immer mal wieder schreiben ist überhaupt 
kein problem...

Ein Problem könnte sein, wenn man oft innerhalb einer Datei hin und her 
springt. Beispiel:
Ich schreibe in Sektor 1928 ein Byte, jetzt springe ich (mit ffseek) zu 
Sektor 1929 und schreibe wieder ein Byte, weil ich aber Sektor 1928 
verlasse und dieser geändert wurde, muss er vorher geschrieben werden.

Wenn ich jetzt zurück springe, passiert das gleiche wie vorher mit 
Sektor 1928 jetzt mit Sektor 1929.
Das ist der schlimmste Fall, weil für nur 1 geändertes Byte immer ein 
ganzer Sektor geschrieben wird... Würde also 512 Sektor schreib Vorgange 
(also 512*512 Bytes) für 512 Bytes machen. Das wäre schlecht und 
langsam...

Wenn eine Datei angelegt wird, gibt es mindestens 3 Sektor schreib 
Operationen.

1. Anlegen des Datei Eintrags im Ordner.
2. Mindestens einen Sektor mit Daten beschreiben (auch wenn weniger 
Bytes geschrieben werden).
3. Update des Datei Eintrags (Größe usw.).

Macht 3 beschriebene Sektoren. Das wird so gemacht, weil wenn schon mal 
ein Datei Eintrag besteht, kann man mit Recovery-Tools möglicherweise 
bei Datenverlust Daten retten. Dient also rein der Sicherheit. Nötig 
wären nur 2 Sektor schreib Operationen...

Da ein Sektor (512 Bytes) die kleinste Einheit ist die man auf eine 
Karte schreiben kann werden ja eben 512 Bytes gepuffert.

Grüße Daniel

von Chris (Gast)


Lesenswert?

Ok,
vielen Dank dafür!!
Das mit dem ffclose werde ich berücksichtigen.

Gruß
Christian

von Matze A. (matzeapa)


Lesenswert?

Hi,

ich habe noch einen kleinen Zusatz zur file.c (ist vielleicht etwa 
übertrieben, aber vielleicht als Addon nicht schlech):
Wenn man z.B. Messwerte aufnehmen will, macht ein Zeilenumbruch recht 
viel sinn. Ich habe in meine file.c daher hinzugefügt:
1
ffzeilenumbruch ()
2
   {
3
     ffwrite(0x0D);
4
     ffwrite(0x0A);
5
   }

Macht zugegebener Maßen nicht in jeder Anwendung sinn, bei mir 
allerdings schon und ich denke auch bei so mach anderem.

Gruß,
ein Fan dieser Speicherfressenden Library :)
Matze

von Martin (Gast)


Lesenswert?

Hallo Daniel,

ich habe nun die LIB ausfuehrlich getestet und muss sagen, dass alles 
rund laeuft. Meine HireScore-Liste laeuft nun auch und wartet auf die 
Besten.

Gruss Martin

von C.Alex (Gast)


Lesenswert?

Hallo,

ich hab heute die Souce-Files mit WinAVR (ohne mitgelieferte makefile) 
compiliert und es kommt tatsächlich ein Hex-File.
uc=atmega8
optimierung= -Os
smallFileSys 0
write 0
superfloppy  1

Program:    7826 bytes (95.5% Full)
(.text + .data + .bootloader)

Data:        656 bytes (64.1% Full)
(.data + .bss + .noinit)

Als hab ich den parameter smallFileSys 1 gesetzt. Die Größe ist aber bei 
den 7826 byte geblieben.

Ich weiß, dass das Problem bekannt ist. Gibt es dazu schon eine Lösung?



Viele Grüße
C.Alex


PS: Die mitgelieferte makefile hat auch keine abhilfe gebracht.

von daniel (Gast)


Lesenswert?

Hallo,
bin leider noch nicht dazu gekommen, die beiden Optionen von 
smallFileSys und write wieder einzubauen...
Nur superfloppy funktioniert bis jetzt.
Wird wohl auch noch ein wenig dauern, weil ich auch alles auf 
dynamischen Ram verbrauch am umbauen bin...

Grüße Daniel

von C.Alex (Gast)


Lesenswert?

Hallo,

das erklärt natürlich einiges :)

Ich dachte AVRStudio würde wieder rumspinnen. Ich muss auch zugeben, ich 
hab nicht alle 180 Beiträge oben gelesen...


Was aber trotzdem interessant ist: Ich wollte den Code für ATmega88 
compilieren und auf einmal hat er nicht mehr draufgepasst (500byte zu 
groß).
Laut Datenblatt sind aber atmega8 und atmega88 von den Speichern her 
gleich groß. Tja Sachen gibts...

Danke für die Info

Viele Grüße
C.Alex

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Hallo zusammen.
Jetzt sind wieder alle 3 Schalter in der Lib zu benutzbar.
Zudem einige Verbesserungen.
Lesend ist bis zu 230 KBytes/s möglich. Beim Roh lesen, also ohne 
Dateisystem kommt man ungefähr auf 300 KBytes/s. Das ist nur ein relativ 
geringer Overhead.
Schreiben geht jetzt bis zu 140 KBytes/s trotz 
überschreiben-Funktionalität.

Bisschen Doku gibts auch hier :
http://www.mikrocontroller.net/articles/AVR_FAT32

PS: Die Zeilenumbruch Funktion wird erstmal nicht aufgenommen, 
allerdings sind weitere Anregungen erwünscht.

Viel Spaß damit :)

Grüße Daniel

von C.Alex (Gast)


Lesenswert?

Hallo Daniel,

die neue Version passt mit 94% Flash-Auslastung wunderbar auf dem 
atmega88.


Beim ersten Compilieren hat er mit smallFileSys 1 die Funktion 
fat_str(datei) nicht gefunden.

Ich hab dann einfach die Präprozessoranweisung in fat.c geänder in:
1
#if (smallFileSys==1)
2
// *****************************************************************************************************************
3
// bereitet str so auf, dass man es auf die mmc/sd karte schreiben kann.
4
// wandelt z.b. "t.txt" -> "T        TXT" oder "main.c" in "MAIN    C  " => also immer 8.3 und upper case letter
5
// VORSICHT es werden keine Prüfungen gemacht !
6
// *****************************************************************************************************************
7
char * fat_str(char *str){
8
.
9
.
10
.
11
}
12
13
#endif

Viele Grüße
C.Alex

von C.Alex (Gast)


Lesenswert?

Hallo,

mit welchem Programm muss ich meine SD-Karte formatieren, damit ich 
sicher gehen kann, dass es fehlerfrei formatiert ist.

Hintergrund ist, dass ich ein LowLevel-Format gemacht hab um den 
Speichervorgang nachvollziehen zu können. Anschließen mit Windows 
formatiert in FAT16. Seit dem schlägt die Fat-Initialisierung fehl. 
Also: Boot...

Vorher ging es.
1
#include <stdlib.h>
2
#include <avr/io.h>
3
4
#include "main.h"
5
#include "file.h"
6
#include "fat.h"            
7
#include "hardware.h"
8
9
void beispiele(void);      // kleine datei operations-beispiele
10
11
//*****************************************************************************************************************
12
void main(void){
13
14
  uinit();              // uart initialisierung
15
 
16
  uputs((unsigned char*)"\nBoot");
17
18
  while (mmc_init() !=0){     //ist der Rückgabewert ungleich NULL ist ein Fehler aufgetreten  
19
  ;  
20
  }  
21
  
22
  uputs((unsigned char*)"... ");    
23
24
  if(0==fat_initfat()){        //ist der Rückgabewert ungleich NULL ist ein Fehler aufgetreten  
25
26
   uputs((unsigned char*)"Ok\n");    // wenn auf dem terminal "Boot... OK" zu lesen ist, ist init ok. jetzt kann man schreiben/lesen
27
28
    beispiele();                // beispiel 0-4 , da nur atmega8, keine ordner anlegen und ordner rekursiv löschen...
29
  }
30
31
32
}
33
34
// *****************************************************************************************************************
35
void beispiele(void){
36
37
  char datei[12]="test.txt";    // hier muss platz für 11 zeichen sein (8.3), da fat_str diesen string benutzt !!
38
  fat_str(datei);            // wandelt "test.txt" in das fat format 8.3 der form: "TEST    TXT" muss immer dieses Format haben, auch ordner !!
39
40
  // 1.) ______________anlegen und schreiben____________________________________________________________________
41
  /*   öffnet datei, wenn nicht vorhanden, legt ffopen datei an (rückgabewert = 1 datei existiert, also nur öffnen, 2 = angelegt). */  
42
  uputc('\n');
43
  uputs((unsigned char*)"Datei anlegen\n");
44
  ffopen( datei );            
45
46
  /* schreibt string  */
47
  ffwrites((char*)"Hallo Datei :)");
48
  // neue zeile in der datei
49
  ffwrite(0x0D);
50
  ffwrite(0x0A);
51
52
  /* schließt datei */
53
  ffclose();
54
  uputs((unsigned char*)"Ende\n");
55
  
56
}
57
//*****************************************************************************************************************


Ich hab doch im Prinzip nichts falsch gemacht? oder?


C.Alex

von Sucher (Gast)


Lesenswert?

Hallo

@Daniel weiter oben schreibst Du, dass Du einen HC4050 als Levelshifter 
verwendest. Ist der wirklich geignet? Im Datenblatt steht das VCC -0,5 
bis 7V sein kann (also VCC=3,3V). DC Input Voltage -0,5V to Vcc+0,5V. 
Das wären dann aber bis 3,8V, also keine 5 V. Das der das eventuell ohne 
kaputt zu gehen kann ist ne andere Sache!
Oder habe ich da was falsch verstanden?

Danke für ne Klärung
Achim

von Daniel R. (zerrome)


Lesenswert?

Hallo zusammen.

@Alex
Wahrscheinlich ist die Karte jetzt nicht mehr partitioniert, du musst 
also in der fat.h "superfloppy  1" ändern.

@sucher

Ausschnitt Datenblatt:

"The 74HC4050 provides six non-inverting buffers with a
modified input protection structure, which has no diode connected to 
VCC. Input voltages of up to 15 V may therefore be used. This feature 
enables the non-inverting buffers to be used as logic level translators, 
which will convert high level logic to low level logic, while operating 
from a low voltage power supply. For example 15 V logic
(“4000B series”) can be converted down to 2 V logic."

Das verstehe ich so, dass da eine irgendwie geartete Eingangssicherung 
besteht, damit der Eingang nicht kaputt geht. Deshalb kann man bis zu 
15V auf den Eingang machen selbst wenn das Ding nur mit 2V betrieben 
wird.
Rest vom Datenblatt gibt das auch so her...

Grüße Daniel

von Sucher (Gast)


Lesenswert?

Hallo

@Daniel, Danke für die Antwort. Es gibt da wohl verschieden Datenblätter 
( Deins ist Philips?).
Bei Reichelt könnte man das nich rauslesen
http://www.reichelt.de/?;ACTION=6;LA=3;ARTICLE=3228;GROUPID=2933;GROUP=A2235;SID=31XMMj3qwQAR8AAApHlEkae535059485831c5f64f055c1b01bd7a 
(Thomson)

Es geht mir nicht ums rechthaben, sondern ich möchte es verstehen.

MfG
Achim

von C.Alex (Gast)


Lesenswert?

Hallo Daniel,

die Initialisierung der Karte und FAT funktionieren jetzt wieder, 
allerdings bleibt das Beilspielprogramm gleich in dem ersten 
Funktionsaufruf hängen. Also bei:
1
.
2
.
3
.
4
char datei[12]="TEST    TXT";
5
ffrm(datei);
6
.
7
.
8
.

Daraufhin hab ich die Signalwandlung mit dem SN74LS07 geprüft, es ist 
aber alles OK.

Hast du eine Idee warum der uC da hängen bleibt? Gleiche Reaktion mit 2 
versch. Karten.

Danke!

C.Alex

von Daniel R. (zerrome)


Lesenswert?

Hallo.


@Achim

Tatsache, in dem Datenblatt von Thomson steht nur ein schlanker Satz 
dazu, im Rest der Daten finde ich das auch nicht so bestätigt..

"The VCC side diodes are designed to allow logic-level convertion from 
high-level voltages (up to 15 V) to low-level voltages."



@C.Alex

So wie es aussieht, gibt es möglicherweise Probleme mit FAT16 und nur 
einem Sektor pro Cluster... hatte ich nicht getestet, sorry.
Werd ich aber schleunigst beheben.
Bis zum erbrechen hatte ich FAT32 mit mehreren Sektoren pro Cluster 
getestet...
Als workaround, meine Empfehlung: FAT32 mit mehreren Sektoren pro 
Cluster.

Grüße Daniel

von C.Alex (Gast)


Lesenswert?

Hallo Daniel,

ich habe beide Karten mit FAT32 formatiert; kein Unterschied zu vorher. 
Bedenken habe ich im Zusammenhang mit der Formatierung der Karten. Kann 
man davon ausgehen, dass das Windows Formatier-Tool alles richtig macht?

Weil: ich hab die Karte mit Windows formatiert und hatte danach das 
Problem, dass es nicht mehr gebootet hat :Boot...
Daraufhin hab ich es in meine Digicam reingesteckt, der kein System 
erkannt hat und formatieren wollte, und siehe da: Boot...OK

Ich kenn mich nur zuwenig mit FAT aus um dem auf den Grund zu gehen.

C.Alex

von Daniel R. (zerrome)


Lesenswert?

Hallo,

also das einzige Problem ist die Formatierung mit Linux, da dabei, warum 
auch immer, das root-Dir wenn es nur 1 Cluster groß ist als Ende 
Markierung nicht 0xfffffff0 erhält, sondern 0xffffff80.
Ich hatte einfach keine Lust mich mit 3 Ende Markierungen 
herumzuschlagen.

Windows ist manchmal etwas eigen beim Formatieren, da wird schon mal aus 
einer partitionierten Karte eine unpartitionierte ohne Kommentar ^^
Muss man nachsehen und in der Lib umstellen.

Andere Probleme gibt es eigentlich nicht im Zusammenhang mit 
Formatierungen.

Was haben die Karten, die nicht durch den Boot Vorgang kommen, denn für 
Eckdaten? MB Größe, Sektoren/Cluster und partitioniert oder 
unpartitioniert?

Grüße Daniel

von C.Alex (Gast)


Lesenswert?

Hallo,

da wäre:
Lexar Media
File System: FAT16
Total capacity: 127.090.176 byte
Sector count: 248.223
Bytes per Sector: 512
Bytes per Cluster: 2.048
Total Clusters: 61.925


Lexar Platinum II
File System: FAT16
Total capacity: 512.880.128 byte
Sector count: 1.001.719
Bytes per Sector: 512
Bytes per Cluster: 8.192
Total Clusters: 62.574

Woran kann ich erkennen, ob nach dem formatieren eine Karte 
partinioniert ist oder nicht?


C.Alex

von Daniel R. (zerrome)


Lesenswert?

Also einmal steht im Sektor 0 die Partitionstabelle oder die Fat Daten.

Bei beiden von Dir geposteten Karten sollte angesprochenes Problem mit 
nur einem Sektor pro Cluster nicht auftreten.
Bleibt nur noch die Partitionierung und das Formatieren mit Linux.
Das mit der Partitionierung ist schnell getestet... einfach mal 
umstellen in der Lib und schauen ob es geht. Allerdings besser nur ein 
lese Test (also auch kein ffrm !).

Es kann auch vorkommen, dass die Initialisierung der Fat durchläuft, 
aber keine sinnvollen Daten enthält. Dann würde sich z.B. ffrm ziemlich 
aufhängen. Würde zu Deinem Problem Passen. Wäre aber zurückzuführen auf 
die Falsche Vorgabe des Schalters "superfloppy" in fat.h

Grüße Daniel

von C.Alex (Gast)


Lesenswert?

Hallo Daniel,

ich hab den Parameter SUPERFLOPPY mit beiden Einstellungen ausprobiert 
und versucht einer vorher unter Windows erstelle TEST.TXT nur zu lesen 
und auf dem Terminal darzustellen.

Bei einer Einstellung ist der Bootvorgang nicht beendet worden: Boot... 
und es wurde auch nichts weiteres angezeigt.
Mit der anderen Einstellung wurde der Bootvorgang abgeschlossen und das 
ganze Terminal wurde mit irgendwelchen Daten vollgeschrieben.


Unter Linux hab ich noch nicht formatiert.


C.Alex

von Daniel R. (zerrome)


Lesenswert?

Hallo,

kann ich absolut nicht bestätigen. Hast du irgendwo den Code geändert?
Habe nochmal alles durchgesehen und getestet, dabei ist mir noch ein 
anderer Bug aufgefallen..in Zusammenhang mit ffseek und dem 
überschreiben von Daten. Sonst ist da alles im grünen Bereich !

Grüße Daniel

von Johannes N. (strangeman)


Lesenswert?

Hallo!

Ich bin begeistert von der Lib! Wer hätte gedacht, dass das SD-benutzen 
so einfach wird? =)

Alles funktioniert soweit ok. Zum Testen habe ich eine AgfaPhoto 1GB 
genommen. Ich schreibe mit einem Delay von 10ms 2000 uint_16t Werte und 
ihre Nummer als String auf eine Textdatei. Geht sauber und schnell. 
Allerdings scheint es so, dass ich nochmal warten muss (ich hab jetzt 
100ms) bevor ich ffclose aufrufe, da sonst die Datei nicht vollständig 
ist. Vermutlich wegens des Hardware SPI? Vielleicht könnte ffclose 
selbst solange warten, bis die Datei komplett ist!

Bei mir gings auch auf einer 16MB FAT12 Karte, aber da gab es Probleme 
mit dem Schreiben (hatte keinen delay vor ffclose(), aber es fehlten am 
Ende 400 Werte!). Zudem wurden andere Dateien durch das Schreiben der 
Werte verändert. Ich kann ja mal das Image schicken, wenn Interesse für 
FAT12 Support besteht. (Und mir jemand erklärt, vo unter dev die Datei 
für meinen SD-Leser steht...)

Danke für deine Mühen!
StrangeMan

PS: Verwende 0.5.2

von Daniel (Gast)


Lesenswert?

Hallo,

also die SPI Routinen sind blockend geschrieben, die warten solange bis 
das
Byte das geschrieben werden soll auch raus ist.
Deshalb ist ein delay unnötig.
Wenn es aber mit einem delay klappt, klingt das für mich eher so, als ob 
die SPI Strecke anfällig ist. Vielleicht schwingt da was mit oder so 
(und beruhigt sich bei einem delay?!?)...
Wie steuerst Du die Karten an? Direkt oder über irgendwelche 
Pegelwandler?


Komme momentan nicht richtig zum weiter entwickeln.
Was aber definitiv geht ist einfaches lesen und schreiben ohne die etwas 
ausgefalleneren Funktionalitäten wie ffseek() und überschreiben von 
Daten.

Wobei ffseek() an sich tadellos funktioniert, nur in Zusammenhang mit 
ffwrite() und dem überschreiben welches über einen Sektor hinaus geht 
gibt es Probleme, da dann ja der Sektor in dem man jetzt weiter 
überschreiben möchte noch geladen werden muss...

Grüße Daniel

von Onit (Gast)


Lesenswert?

Noch zum Thema Zeilenumbruch:
Wichtig ist das die Angabe der Zeichenanzahl beim Schreiben auf die 
SD-Karte!!!!
"\r\n" sind nur 2 Zeichen nicht 4!!!!!
Bei der Angabe, das es 4 Zeichen sind, werden die letzten 2 Zeichen 
(nach dem Zeilenumbruch)irgendwelcher Käse. Meist sind da 4ecke 
enthalten, oder der Inhalt anderer Daten.

von Sucher (Gast)


Lesenswert?

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

MfG
Achim

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

von Daniel (Gast)


Lesenswert?

Hallo.

@Onit
Da ein '\n' halt auch nur ein Char/Byte ist, wird da schon nix doppelt 
gezählt..

@Sucher
Bei meiner Lib werden halt immer 512 Bytes zwischengespeichert, da auch 
immer 512 Bytes direkt auf die Karte müssen. Daher ist die Langlebigkeit 
genau so, als wenn ein Pc auf die Karte schreibt...Nur das der 
vielleicht noch bisschen mehr Puffert als es mit einem MC möglich ist..


Grüße Daniel

von Sucher (Gast)


Lesenswert?

Hallo

@Daniel das heißt, wenn ich kleinere Einheiten als 512 Byte schreibe 
wird das in deinem Interface gepuffert? Muss man da beim Schreiben dann 
die Bytegrenzen (512 Byte Blockung) als Anwender beachten?
Es wird also solange gepuffert bis 512 Byte erreicht sind. Wenn ich nun 
einen String schreibe der über die 512 Byte geht wird dann ein 512 Byte 
String auf die SD Karte geschrieben und der Rest gepuffert? Wenn nur 
gepuffert wird ist der Schreibvorgang schneller, als wenn eine 
Blockgrenze überschritten wird und auf die SD geschrieben wird. Wie 
lange dauert dann dieser Aufruf (klar Proz abhängig)?

Wird bei jedem Blockschreiben die FAT auf der SD Karte aktualisiert? 
Falls ja wäre das  ja der kritische Punkt mit dem "kaputt" gehen der SD 
Karte, oder wird nur beim Schließen des Files aktualisiert?

Fragen über Fragen...

Vielen Dank
Achim

von Daniel R. (zerrome)


Lesenswert?

Hallo Sucher,

ja richtig. In der Lib gibt es einen 512Byte Puffer. Ist dieser voll, 
wird die Karte mit diesen Bytes beschrieben.

Erst bei ffclose() erfährt der Dateieintrag und die Fat eine 
Aktualisierung. Es werden immer freie Cluster in einer Reihe gesucht, 
ist diese Anzahl voll, so werden diese auch schon in der Fat verkettet. 
Wird erst zum Problem, wenn die Fat total fragmentiert ist...

Eine Datei bei FAT-Dateisystemen ist Quasi in 3 Teile aufgeteilt:
1. Datei Eintrag mit Name,länge usw in einem Ordner.
2. FAT Einträge
3. Die Daten selber

Siehe auch: http://www.mikrocontroller.net/articles/AVR_FAT32

Wer mag kann mit "int i=file.cntOfBytes;" abfragen wie viele Bytes in 
dem Puffer schon geschrieben sind. Bei 512 wird auf die Karte 
geschrieben...

Wie lange jetzt genau das schreiben eines 512Byte Blocks dauert müsste 
man mal testen :)
Ebenso wie lange es dauert neue freie Cluster aus der Fat zu suchen oder 
solche Cluster zu verketten...

Grüße Daniel

von Sucher (Gast)


Lesenswert?

Hallo

@Daniel noch ne Frage(n): Kann man beim Öffnen ne Dateigrösse angeben, 
dass die entsprechenden Cluster gleich vekettet werden, ohne dass man da 
explizit reinschreibt?

Oder geht das mit ffseek übers Dateiende hinaus...wird dann reserviert, 
oder darf bei ffseek der Offset nicht übers Dateiende rausgehen?

Gibts dafür ne andere Möglichkeit?

Vielen Dank
Achim

von Daniel R. (zerrome)


Lesenswert?

Moin,

also ffseek() darf auf keinen Fall über das Dateiende hinaus. Gilt nur 
für innerhalb einer Datei, bis zum letzten Byte.

Also vorher die Datei Größe bestimmen? Wieso?
Wäre schon machbar, mir erschließt sich aber nicht der Grund wieso man 
das machen sollte.
Wenn es um Geschwindigkteit geht, einfach dafür sorgen, dass die Fat 
nicht fragmentiert ist. dann könnten bis zu 65000 Cluster am Strück mit 
Daten voll gemacht werden, bevor diese verkettet werden müssen (müsste 
man nur 2 Zahlen in der Lib ändern).

Mal mit Zahlen:

4 Sektoren Pro Cluster.
512 Bytes Pro Sektor.
65000 Cluster.

Macht 126,95 Mega Bytes am Stück, ohne etwas mit der Fat oder dem 
Dateieintrag machen zu müssen :)

Bei 65000 Clustern, die in der Fat verkettet werden müssen, müssen 508 
Fat Sektoren geschrieben werden, macht 206096 Bytes. Also etwa 254 
KBytes. Die bekommt man so in etwa 2 Sekunden beschrieben...

Grüße Daniel

von Sucher (Gast)


Lesenswert?

Hallo

@Daniel ich bin eben dabei die einzelnen Implementierungen abzuklopfen.
In der Implementierung von Roland Riegel wird sowas diskutiert, dass man 
am Anfang gleich einen großen File allokiert weil sonst das Anfügen 
lange dauert.
zB.:Beitrag "Re: MMC/SD-Karte mit FAT16 an AVR"

Ich muß halt mal damit spielen und Erfahrungen sammeln...

Vielen Dank
Achim

von Daniel R. (zerrome)


Lesenswert?

Hi Achim,

den Code von Roland versteh ich teilweise nicht genau.
Aber generell dauert es halt ein bisschen die Fat zu updaten und neue 
freie Cluster zu suchen.
Zuerst hatte ich da auch eine etwas sperrige Methode. Jetzt geht das 
total schnell, wenn halt die Fat nicht groß fragmentiert ist.

Wenn du da irgendwo Vorteile/Nachteile siehst, könnte man das ja mal 
zusammen tragen und als Vergleich ins Wiki stellen...

Grüße Daniel

PS: hab mich da oben bei einer Ziffer vertan, muss natürlich 260096 
Bytes heißen^^

von Johannes N. (strangeman)


Lesenswert?

Ich habe noch ein Problem. file.length ist bei mir negativ (-492). Es 
ist aber eine Datei geöffnet und ich kann ganz ordentlich daraus lesen.

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Hallo,

sehr seltsam. Wie kommst du denn auf -492 ?
Weil eigentlich dachte ich das ein "unsigned long int length" (siehe 
fat.h) niemals negativ werden kann.
Lässt du dir das vielleicht falsch anzeigen?
Nimm mal die neue Version, vielleicht wirds dann besser.

Hab jetzt auch die bekannten Bugs beseitigt.

Es gibt 2 neue Schalter in der fat.h.

1. OVER_WRITE
Gibt an ob die Datei überschreiben Funktionalität mit Kompiliert wird.
Da wenn überschrieben wird auch immer der zu überschreibende Sektor 
geladen werden muss, ist meine Empfehlung "OVER_WRITE 0" zu setzen und 
auf überschreiben zu verzichten.

2.MAX_CLUSTER_IN_ROW
Gibt an wie viele verkette bzw. leer Cluster für eine Datei gesucht 
werden, maximaler Wert, 65 534.

Grüße Daniel

von Johannes N. (strangeman)


Lesenswert?

Inzwischen habe ich es herausgefunden: warum der unsigned long int nun 
negativ war weiß ich nicht, aber deine Lib hat mir die Datei 4GB groß 
gemacht, obwohl die Karte nur einen GB hat... nun gehts aber.

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Hallo,

ja das mit der Dateigröße ist mir dann doch noch klarer geworden. Unter 
Umständen waren auf file.length noch alte Daten vom durchsuchen von 
alten Ordnern... hatte da aufgrund von Codegröße alles mögliche gekürzt 
^^

Da überschreiben von Daten so kompliziert ist und deshalb relativ 
langsam, gibt es 2 Funktionen zum schreiben, die über den schon 
erwähnten Schalter OVER_WRITE in fat.h wahlweise mit ein Kompiliert 
werden können.

Der Code ist diesmal wirklich stabil, da ich ausgiebig Zeit zum testen 
hatte.
Anregungen und Tipps immer willkommen.

Als Anhang die neue Version mmc-0.5.3

Es ist dringend zu empfehlen, entweder die Version mmc-0.4.8 oder die 
neue zu benutzen !

Grüße Daniel

von Daniel R. (zerrome)


Lesenswert?

Wiki auch geupdatet. Vor allem "Interne Technik"

http://www.mikrocontroller.net/articles/AVR_FAT32

von Sucher (Gast)


Lesenswert?

Hallo

@Daniel mal ne blöde Frage "Wann wird eine FAT fragmentiert"?

..doch nur wenn ich eine Datei schließe ne neue öffne und schreibe 
schließe und die alte Datei öffne und was dran hänge...

oder eine Datei lösche und ne neue mit verschiedener Größere schreibe?

Macht es da nicht Sinn (meine oben gestellte Frage) dass man beim Öffnen 
oder seek die Deitei auf eine bestimmte grösse aufblähen kann ohne 
reinzuschreiben?

MfG
Achim

von Daniel R. (zerrome)


Lesenswert?

Hallo Achim,

eine Fat fragmentiert, wenn man Daten löscht. weil da wo vorher die 
Cluster einer Datei in der Fat verkettet waren, nun Cluster frei sind.

Die von Dir beschriebenen Probleme sind dann nur die Folge draus...

Das Problem ist, ich möchte die Lib so allgemein wie möglich halten. 
Natürlich müsste man, wenn etwas sehr Zeitkritisch ist testen und ggf. 
die Lib anpassen.

Oder sogar alles auf eine spezielle Gegebenheit umschreiben und zusammen 
kürzen. Mir geht da z.B. eine Einzige Funktion durch den Kopf, die eine 
ganze komplett vordefinierte Datei schreibt oder ähnliches...

Das mit dem vorher allozieren wäre garkein Problem, nur ich gehe mal 
davon aus, nicht vorher zu wissen wie lang eine Datei wird.

Vielleicht baue ich noch ein, dass man beim schreiben immer mindestens 
MAX_CLUSTERS_IN_ROW freie bekommt. Und/Oder eine Funktion, die die 
letzte Datei in der Fat ermittelt und erst danach mit schreiben anfängt.

Grüße Daniel

von Kricke (Gast)


Lesenswert?

Hallo,

ich versuche gerade den Code zu verwenden, leider ohne den gewünschten 
Erfolg. Ich habe die letzte Version benutzt und momentan sieht mein Code 
so aus:

[c]

int main (void)
{
  //wdt_enable(WDTO_1S);

  sei();

  initUart();
  sendEOL();
  uartPutS("Serveur de temps");
  sendEOL();

  if(mmc_init() == 0)
  {
    uartPutS("SD-Card Inizialisation failed.");
    sendEOL();
    while(1) {};
  }

  uartPutS("SD-Card initialized.");
  sendEOL();

  if (fat_initfat() == 0)
  {
    uartPutS("FAT initialized.");
    sendEOL();

    char datei[12]="test.txt";

    fat_str(datei);

    switch (ffopen(datei ))
    {
      case 1:
      {
        uartPutS("Existing file opened.");
        sendEOL();
      }
      case 2:
      {
        uartPutS("New file created and opened.");
        sendEOL();
      }
      default:
      {
        uartPutS("Cannot create or open file.");
        sendEOL();
      }
    }

    ffwrites((char*)"Hallo Datei :)");
    ffwrite(0x0D);
    ffwrite(0x0A);

    uartPutS("Data written to file.");
    sendEOL();

    ffclose();
    uartPutS("File closed.");
    sendEOL();
  }

  while(1) {};
}

[\c]

Die Initialisierung klappt, nur beim ffopen() bzw genauer in der Routine 
unsigned char fat_loadFileDataFromDir(char name[]) hängt der Prozessor 
sich auf. Nach meinen bisherigen Nachforschungen sind die ausgelesenen 
Sektoren alle '0' und der Prozessor hängt. Auf dem SPI-Bus ist nichts 
mehr los. Was mich wundert: Die Karte wird als FAT32 erkannt, auch wenn 
sie auf FAT16 formatiert wurde. Ich habe sowohl FAT32 als auch 16 
ausprobiert und auch SUPERFLOPPY geändert, ohne Erfolg.

Hat jemand eine Idee, woran es liegt?

von Kricke (Gast)


Lesenswert?

Ok, die Initialisierung läuft irgenwie auch nicht: Selbst ohne Karte 
läuft mmc_init() durch... :-(

von Daniel R. (zerrome)


Lesenswert?

Hallo,
also besser ist sowas für mmc_init() :
1
while (mmc_init() !=0){
2
  ;  
3
  }

Da es sein kann das es etwas dauert bis die Karte "anspringt".
Sieht sonst OK aus.
Vielleicht mal den SPI Takt bisschen runter setzen.
Wie hast du die Karte angeschlossen?

Grüße Daniel

von Kricke (Gast)


Lesenswert?

Der SPI-Takt liegt bei etwa 120kHz, die Karte ist direkt an einen 
Atmega644p angeschlossen, der mit 3,3V läuft. Ein Pull-Up an DO ist 
dran.

Deinen obigen Vorschlag habe ich schon umgesetzt, aus der Schleife kommt 
der Controller bzw. die Karte nicht raus. Ich lese mir mal die 
Bedienungsanleitung meines Logigports durch...

von Daniel R. (zerrome)


Lesenswert?

Mit mmc_init() hatte ich bis jetzt nur Probleme, wenn die Kabel zur 
Karte zu lang waren, aber bei 120KHz dürfte das kein Problem sein.

Vielleicht mal andere Karten ausprobieren, Schaltung überprüfen sonst 
hab ich keine Ahnung wieso die mmc_init() nicht durchläuft.

Hm über was wird die Karte mit Strom versorgt? Da können Peaks bis zu 
60mA auftreten, und Ripple auf der Versorgungsspannung ist auch 
schlecht...

Mach doch mal ein Foto von der Schaltung :)


Grüße Daniel

von Kricke (Gast)


Lesenswert?

Hallo Daniel,

vielen Dank fuer die Tipps. Auf so einen Mist muss man erst einmal 
kommen: Der SD-Kartenhalter von ALPS hatte an zwei Pads keinen 
Kontakt... Da der groesstenteils geschlossen ist, kam man da nicht ran. 
Das ganze hat lich jetzt eine 2GB-Karte gekostet, aber die sind ja 
guenstig inzwischen.

Jetzt habe ich gerade meine erste Datei angelegt und beschrieben. Wenn 
der Rest auch so gut laueft, waere das sehr cool. Danke fuer die 
Bibliothek. :-)

von Daniel R. (zerrome)


Lesenswert?

Hi,
schön, dass es jetzt klappt,
schade das ne Karte drauf gegangen ist ^^
Aber sowas kurbelt ja die Konjunktur an :)

Grüße Daniel

von Emperor_L0ser (Gast)


Lesenswert?

Moin, ich bin grade dabei deine Bibliothek zu testen. Ich habe hier 3 
SD-Karten liegen (1x 128MB, 1x 256 MB von toshiba und 1x 2GB von san 
disk), allerdings gibt es Probleme beim Schreiben. Mein Prozessor ist 
ein AT90CAN128, welcher mit 3,3V läuft und vom internem Takt versorgt 
wird.

Hier eine genauere Fehlerbeschreibung:
-Lesen geht.
-Löschen von Dateien geht.
-Anlegen einer nicht vorhandenen Datei geht nur jedes 2. mal, wobei die 
Funktion nie zurückkehrt, egal ob eine Datei auf der SD-Karte angelegt 
wurde oder nicht.
-Schliessen einer Datei, bei der sich Daten geändert haben geht nicht, 
es werden also nie Daten geschrieben.

Alle Schreibversuche auf die SD-Karten enden damit, dass der Prozessor 
sich dauerhaft mit der SD-Karte unterhält, welcher Befehl übers SPI 
läuft kann ich leider nicht sagen.

Die SD-Karten habe ich zwischendurch immer wieder mit Windows auf FAT32 
formatiert. Die Einstellung SUPERFLOPPY habe ich sowohl gesetzt, als 
auch nicht gesetzt probiert.

Eine genauere Beschreibung kann ich mangels JTAG-Interface leider nicht 
geben.

mfg Emperor_L0ser

von daniel (Gast)


Lesenswert?

Hallo,
hast du irgendwo den Code geändert?
Wie rufst du die Funktionen auf?

Versuchst du zu überschreiben? Dann muss "OVER_WRITE 1" und "WRITE 1" 
gesetzt sein.

Grüße Daniel

von daniel (Gast)


Lesenswert?

ach äh welche Version benutzt du? 0.5.3 ?

von Emperor_L0ser (Gast)


Lesenswert?

Moin,
ja ich habe den Code geändert, dies beschränkt sich allerdings darauf, 
dass ich alle Variablendefinitionen aus den for-Schleifen entfernt und 
an den Anfang der Funktion gepackt habe (ANSI-C99 Standard, mein avr-gcc 
meckerte). Der AT90CAN128 ist von den Definitionen mit dem ATMega128 
kompatibel, ich musste dort nichts ändern.
Ich verwende Version 0.5.3 und die Dateien, die dort nicht enthalten 
sind (main.c, mmc.c und mmc.h) verwende ich aus 0.5.2. Aufrufen tu ich 
nur die Funktionen, welche in der Beispiel-Funktion der main.c sind.
Write ist die ganze Zeit auf 1, sonst sind die Funktionen ja garnicht 
vorhanden. OVER_WRITE habe ich sowohl gesetzt als auch ungesetzt 
versucht.

mfg Emperor_L0ser

PS: ich verwende nicht die Makefile, meine Befehle, wie für alle meine 
Projekte:

if avr-gcc -O2 -mmcu=at90can128 -DF_CPU=1000000 ./*.c
then
        avr-objcopy -O ihex -R .eeprom a.out flash.hex
        avrdude -p c128 -e -c pony-stk200  -U flash.hex
        exit 1
fi

von daniel (Gast)


Lesenswert?

Hallo,

da liegt das Problem, es gibt Funktionen, da muss man noch Code 
ergänzen, damit man die Definitionen nach oben schreiben kann.

Versuch mal dem avr-gcc "-std=gnu99" beizubringen. Dann einfach die 
Original fat.c und file.c dann läufts...

Grüße Daniel

von Emperor_L0ser (Gast)


Lesenswert?

Ich hab es jetzt so gemacht, wie du gesagt hast und es läuft, schonmal 
Danke dafür. Den ersten Teil deiner Antwort versteh ich nicht ganz. Ich 
würd vor allem den Code gerne auch so schreiben, dass er ANSI-C Konform 
ist, da ich ja nicht weiss, ob ich drei Jahren noch den GCC-Compiler 
verwende.

mfg Emperor_L0ser

von Daniel R. (zerrome)


Lesenswert?

Ich bin es von C# und Java gewöhnt überall Variablen zu definieren und 
Deklarieren, is schön bequem, aber is halt kein ANSI-C von 1986...
Eigentlich sollte jeder halbwegs gute Compiler auch ANSI/ISO-C99 können, 
egal.

Hab grad den Code nicht vor Augen, aber man müsste Teile umschreiben, 
damit man die Definitionen an den Anfang der Funktionen setzen kann. 
Musst dir mal genau anschauen was da gemacht wird.

Grüße Daniel

von elral (Gast)


Lesenswert?

Hallo Daniel,

ich habe die Lib zwar noch nicht getestet, scheint aber recht 
interessant für mich zu sein.
Ich frage mich allerdings, wie ich den Inhalt des Directories weiter 
verarbeiten kann. Eine Ausgabe auf die serielle Schnittstelle hilft mir 
nicht weiter (ffls), da ich es auf einem direkt angeschlossenen Display 
ausgeben möchte. Aus einem anderen Beispiel kenne ich zwei folgende 
Funktionen:
* Ermittlung der Anzahl der Directory Einträge
* Ermittlung des Namens des x-ten Directory Eintrages
Können die beiden Funktionen mit den bereits vorhandenen gebildet 
werden? Ich habe da nach Durchsicht Deiner Funktionen aber noch keinen 
Ansatzpunkt gefunden. Wäre es aufwendig, diese beiden Funktionen noch 
einzubringen? Ggf. könnte ich auch Tips gebrauchen, wie das anzugehen 
wäre. Für mich wäre das aber recht zeitaufwendig, da ich in C noch nicht 
so firm bin. Würde ich aber versuchen anzugehen.

Danke und Grüße

Ralf

von daniel (Gast)


Lesenswert?

Hallo Ralf,

wäre nicht sonderlich schwierig.
Mit den beiden vorhandenen Funktionen könnte man so etwas schon 
realisieren, komme ich aber momentan nicht dazu.
Als Hinweis wenn du da selber schonmal was machen willst, "lsRowsOfClust 
(unsigned long int start_sec)" geht durch alle Zeilen eines Clusters, ab 
dem Sektor start_sec. "ffls(void)" geht dann durch alle Cluster eines 
Ordners. Somit hat man beide logischen Strukturen abgearbeitet...

Will man jetzt wissen an welcher "Zeile" welcher Eintrag steht, müsste 
man einen Zähler haben, der von lsRowsOfClust hochgezählt wird, bis man 
an gewünschter Zeile ist.

Will man wissen wie viele Einträge es gibt, würde es reichen anstatt 
einer Ausgabe einfach mit zu zählen, wie viele Einträge ausgegeben 
werden würden.

Grüße Daniel

von elral (Gast)


Lesenswert?

Hallo Daniel,

vielen Dank, Anzahl der Dateien (über ffls) sollte wirklich gar kein 
Problem sein. Das andere muss ich mal sacken lassen :)
Werde ich mir die Tage mal anschauen.

Grüße

Ralf

von Michael P. (protactinium)


Lesenswert?

Moin,

die Lib hat mir viel Arbeit erspart. Habe sie ohne größere 
Schwierigkeiten auf einen MSP430 portieren können. Mir ist dabei nur 
eine Sache aufgefallen. Die Initialisierung der FAT erfolgt ja in 
Abhängigkiet ob "SUPERFLOPPY" 0 oder 1 gesetzt ist. Es ist aber schlecht 
vorherzusagen ob in das fertige Gerät eine Karte eingesetzt wird, die 
ein Superfloppy ist oder aber eine Partition enthält.

Habe die Initialisierung mal so geändert, das automatisch ermittelt wird 
ob ein Superfloppy vorliegt.

1
  //Sektor 0 lesen
2
  if(0==SDC_Read_Block(SDC_READ_SINGLE_BLOCK, 0, 512))
3
  {
4
    vSecOfFirstPartition = (char*)&secOfFirstPartition;
5
    //Startsektor bestimmen
6
    *(char*)vSecOfFirstPartition++=fat.sector[454];
7
    *(char*)vSecOfFirstPartition++=fat.sector[455];
8
    *(char*)vSecOfFirstPartition++=fat.sector[456];
9
    *(char*)vSecOfFirstPartition++=fat.sector[457];
10
    //Prüfung ob man schon im VBR gelesen hat (0x6964654d = Medi)
11
    if(secOfFirstPartition==0x6964654d)
12
      return fat_loadFatData(0);  //Superfloppy liegt vor
13
    else
14
      //FAT-Daten aus dem ersten Sektor der Partition lesen
15
      return fat_loadFatData(secOfFirstPartition);
16
  }
17
  return (1);

Wenn man also eine Karte ausliest und man ist gleich im VBR, dann liest 
man ja innerhalb dieses Abschnittes: "Datentr„ger entfernenÿ 
Medienfehlerÿ Neustart: Taste drcken". An den Positionen 454 - 457 
steht "Medi", was der Sektoradresse 1768187213 entspricht. Diese 
Sektoradresse gibt es bei keiner bisher verfügbaren SD - Karte, weshalb 
man damit auf Superfloppy prüfen kann.

mfg
Michael

von Daniel R. (zerrome)


Lesenswert?

Hallo, sehr schön.

Hatte ich auch immer mal vor das einzubauen, bin aber nicht dazu 
gekommen.
Wird in die nächste Version aufgenommen.

Grüße Daniel

von siegmar (Gast)


Lesenswert?

Hallo Michael,

hab auch schon daran gedacht die Lib auf den MSP430 zu portieren.
Leider noch keine Zeit gehabt.
Hast Du vor, die an den MSP430 angepaßte Lib zu veröffentlichen ?
Noch einen schöne Tag
MfG
Siegmar

PS: Nochmals: Tolle Arbeit von Daniel !!!!!

von zerrome (Gast)


Lesenswert?

Hallo zusammen,

das mit dem veröffentlichen für MSP wird wohl nix werden ^^

Anzupassen wären aber ja eigentlich nur die mmc low level Routinen.
Also die SPI Geschichten.
Hab leider keine Ahnung vom MSP daher schwer abzuschätzen wie viel 
Arbeit das wirklich ist...

Grüße Daniel

von Michael P. (protactinium)


Lesenswert?

Moin,

die meiste Arbeit haben die Routinen für das Lesen und Schreiben der 
SD-Karte gemacht (wegen neu schreiben und so). Bei den FAT- und 
Dateifunktionen habe ich erstmal nur die Void-Pointer (die ICC430 
Version die ich nutze kann damit nicht um), die ganzen Zählvariablen 
angepasst und natürlich die Funktionsaufrufe der Low-Level-Routinen 
geändert. Eben um zu sehen ob es funktioniert. Und es funtkioniert.

Weitere Anpassungen sind sicherlich noch möglich, mach ich irgendwann 
auch noch.

Michael

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

hier mal eine neue Version, gab da noch Bugs...
Zudem ist die SPI schreiben Routine schneller geworden.
Generell kompakterer Code.

Viel Spaß damit :)

Grüße Daniel

von Daniel R. (zerrome)


Lesenswert?

Ach ja, Wiki auch aktualisiert...

http://www.mikrocontroller.net/articles/AVR_FAT32

von Daniel R. (zerrome)



Lesenswert?

Und hier noch der Wiki Artikel als PDF, zum offline lesen :)

von Steffen K. (steffen3)


Lesenswert?

Hallo,
zuerst einmal ein Dank an Daniel dafür, dass er seinen Code hier 
veröffentlicht hat. Ich möchte sein Beispiel nun bei mir lauffähig 
bekommen, es funktioniert aber nicht. Auf der UART-Ausgabe sehe ich, 
dass nach mmc_init() nichts mehr passiert, es muss also ein Fehler in 
fat_initfat() auftreten. Ich verwende eine microSD Karte mit 128MB, die 
ich per Windows als FAT formatiert habe. Wo müsste ich wohl ansetzen um 
den Fehler zu finden?

von Daniel R. (zerrome)


Lesenswert?

Hallo,

wie ist denn die Karte am Controller angeschlossen?
Hast Du etwas am Code geändert?

Du siehst auf dem Terminal "Boot..." und das OK fehlt? Man sollte wenn 
alles richtig initialisiert wird ja "Boot...OK" sehen. Wenn das OK fehlt 
hängt sich das Programm tatsächlich beim Fat auslesen auf. Interessant 
wäre da der Sektor 0 der Karte.
Oder Du könntest einfach mal probieren ob es FAT32 Formatiert klappt, 
ich glaube bei Windows bedeutet nur Fat FAT16 und sonst halt FAT32.

Grüße Daniel

von Steffen K. (steffen3)


Angehängte Dateien:

Lesenswert?

Da ich einen atmega328p verwende, habe ich die mmc.h verändert.
CLK von der Karte habe ich über einen HEF4050 mit SCK am µC verbunden, 
DI auch über HEF4050 an MOSI, CS mit pull-up über HEF4050 an PB1 und DO 
mit pull-up direkt an MISO. An anderen Stellen habe ich nichts im Code 
verändert. Ja es erscheint wirklich nur Boot... . Im Anhang ein Bild vom 
Sektor0, nach dem Versuch darauf zu schreiben.

von Daniel R. (zerrome)


Lesenswert?

Hallo,
also die Karte ist unpartitioniert. Versuch mal folgenden Code, damit 
man feststellen kann ob es an der fat_initfat() liegt oder schon 
woanders hakt.
1
void main(void){
2
  char tmp[10];
3
4
  uinit();
5
6
 
7
  uputs((unsigned char*)"\nBoot");
8
9
  while (mmc_init() !=0){ ;}  
10
  
11
  uputs((unsigned char*)"... ");    
12
13
  fat_loadFatData(0); // läd fat daten
14
15
  
16
  ultoa(fat.rootDir,tmp,10);
17
  uputs(tmp);      
18
  uputc(' ');
19
20
  utoa(fat.secPerClust,tmp,10);
21
  uputs(tmp);      
22
23
}

Jetzt müsste wenn alles funktioniert, "Boot...2 2" zu sehen sein.
Wenn dem so ist muss ich mir die fat_initfat() nochmal genauer 
anschauen.
Wenn nicht, liegt das Problem irgendwo ganz anders. Da würde ich eher 
auf ein Hardware Problem schließen.
Im Datenblatt von dem HEF4050 steht nichts von Versorgungsspannung ab 2 
Volt wie bei dem HC4050, was bei niedrigeren Frequenzen vielleicht noch 
klappt aber dann nach der Karten Initialisierung mit vollem SPI speed 
nicht mehr...

Grüße Daniel

von Steffen K. (steffen3)


Lesenswert?

Als Ausgabe erhalte ich "Boot..." und manchmal "Boot... 0 0" und einmal 
wurde sogar die txt-Datei erstellt, es liegt also an der Hardware. Eine 
2Gb Karte habe ich damit wohl schon zerstört, zumindest reagiert Windows 
nicht mehr, wenn ich die Karte einlege. Aber das die Karte 
unpartitioniert ist verstehe ich nicht, habe es im Arbeitsplatz per 
Rechtsklick und dann auf Formatieren formatiert. Ich werde dann mal die 
74HC4050 von reichelt bestellen und alles neu aufbauen. Schonmal danke 
für die schnelle Hilfe.

von Daniel R. (zerrome)


Lesenswert?

Mir ist noch keine einzige Karte kaputt gegangen bei meinen Tests. Ich 
nehmen aber auch immer sofort den Strom weg, wenn was unvorhergesehenes 
passiert.

Unpartitioniert ist ja nicht unformatiert. Keine Ahnung warum Windows 
mal ne Partition erstellt und mal nicht. Glaube bei kleineren Karten 
wird nicht partitioniert und bei größeren schon.

Du könntest aber auch mal den SPI speed runter setzen und schauen ob es 
dann mit deiner Hardware stabiler läuft.
Einfach in der mmc.c in der Funktion mmc_init () die Zeilen
1
  //SPI Bus auf max Geschwindigkeit
2
  SPCR &= ~((1<<SPR0) | (1<<SPR1));
3
  SPSR = SPSR|(1<<SPI2X);

auskommentieren.

Bei deiner Karte die nicht mehr funktioniert, könnte es sein das die 
mehr als 3,3 Volt abbekommen hat? Mach doch mal ein Foto von der 
Schaltung :)


Grüße Daniel

von Steffen K. (steffen3)


Lesenswert?

Es liegt tatsächlich an dem Speed der SPI, habe es wohl etwas zu frei 
aufgebaut^^, aber jetzt funktioniert es endlich . DANKE;-)

von Daniel R. (zerrome)


Lesenswert?

Schön das es jetzt läuft :)

von Max P. (eizo)


Lesenswert?

Unterstützt das Programm auch Software SPI oder muss man den Hardware 
SPI nutzen?

von Steffen K. (steffen3)


Lesenswert?

ich glaube nur hardware SPI, aber eine software SPI kann man relativ 
leicht implementieren.

von Steffen K. (steffen3)


Angehängte Dateien:

Lesenswert?

ungetest stelle ich hier mal die software SPI rein.

von Steffen K. (steffen3)


Angehängte Dateien:

Lesenswert?

Dieses Mal hoffentlich ohne Fehler.

von Johannes N. (strangeman)


Lesenswert?

Hallo mal wieder!

Ich bastel im Moment wieder mit dem SD-Code rum. Soweit alles in 
Ordnung. Allerdings ist file.seek bei mir immer Null. Das darf aber 
eigentlich nicht sein. Mein Code:
######################################################################## 
#
int main(void) {

  char *tag;
  char *value;
  char s[10];

  lcd_init();
  lcd_clear();

  sd_init();

  lcd_clear();

  tag = malloc(30);
  value = malloc(30);

  char mfile[] = "testdat.txt";
  fat_str(mfile);
  ffopen(mfile);

  // Länge der Datei ausgeben
  lcd_string("L: ");
  lcd_string(itoa(file.length, s, 10));
  lcd_set_cursor(0,1);
  // Position ausgeben
  lcd_string("S: ");
  lcd_string(itoa(file.seek, s, 10));
  _delay_ms(2000);


  while (file.seek <= file.length) {
    tag[0] = '\0';
    value[0] = '\0';

    lcd_clear();
    tpx_read_tag(tag, value);
    lcd_string("T: ");
    lcd_string(tag);
    lcd_string("; S: ");
    lcd_string(itoa(file.seek, s, 10));
    lcd_set_cursor(0,1);
    lcd_string("V: ");
    lcd_string(value);
    _delay_ms(1000);
  }


  ffclose();

  while(1);

  return 0;
}
######################################################################## 
#
tpx_read_tag ist eine funktion von mir, die eine Art pseudo-xml 
realisiert nach dem Muster <tagname=wert>.
Ich brauche file.seek, damit das Auslesen irgendwann mal aufhört.

Noch etwas, ich bekomme warnings:
"./sd/fat.c:96: warning: left shift count >= width of type"

Bis denn dann,
StrangeMan

PS: Am Software-SPI wäre ich auch sehr interessiert! =)

von Daniel R. (zerrome)


Lesenswert?

Hallo,

also so ist file.seek nicht gedacht.
Es wird beim lesen garnicht verwendet. Wenn du bis zum Datei Ende lesen 
möchtest ist die schnellste Variante:
1
unsigned long int seek=file.length;
2
3
do{
4
5
   code zum lesen...
6
7
}while(--seek);

Da so nur geprüft wird ob seek==0 ist als Abbruchbedingung...

Zu dem angesprochenen warning, das hab ich auch, allerdings "nur" beim 
avr-gcc, dem normalen gcc macht das nix. Also hat keine Probleme gemacht 
bei mir. Und den left shift muss man so machen...

Grüße Daniel

von Johannes N. (strangeman)


Lesenswert?

Und wenn ich in dem Moment gar nicht weiß, wo sich der "Cursor" in der 
Datei befindet?
Hmm, da bleibt mir wohl nichts übrig als mir eine globale Variable zu 
machen, die mitloggt, wo ich bin.

von Daniel R. (zerrome)


Lesenswert?

Wie wäre es mit der Variablen seek aus meinem Beispiel?

Ich habe extra darauf verzichtet in ffread() eine 32 Bit variable wie 
file.seek bei jedem einzelnen Byte das gelesen wurde zu ändern...das 
würde bremsen! Besser ist es da die Laufindex Variable (aus dem Beispiel 
eben, seek) beim Aufruf von ffread() zu benutzen.

Wozu genau willst du denn die exakte Position in der Datei wissen?

Und wie gesagt, was spricht gegen die Variable seek?

Grüße Daniel

von StrangeMan (Gast)


Lesenswert?

Hmm, ich hab ein Menüsystem, was auf Basis oben genannter 
Pseudo-XML-Tags die Menüeinträge ausließt. Wenn ich eine Funktion habe, 
die nur einen Tag auslesen soll, dann hat die ja keine Ahnung, wo in der 
Datei sie auszulesen beginnt, wenn ich sie aufrufe. Sie darf aber 
dennoch nicht über das Dateiende hinauslesen. Wenn ich das so amche, wie 
im Code oben, dann kann es ja sein, dass sie erst beim 100ertsten Byte 
anängt zu lesen, weil der "Cursor" da grade war. Dann würde sie 100 
Bytes üebr das Dateiende hinauslesen. Was da bei rauskommt habe ich 
schon gesehen... Zufallsdatan - mehr oder weniger.
Aber ich habs jetzt so gelöst, dass ich einfach mitlogge, wo ich bin. 
Bei jedem ffread() oder ffseek() aktualisiere ich meine globale Varable 
eben.

Das Geschwindigkeitsproblem ist natürlich ein Argument. Aber eventuell 
kann man so eine Seek-Variable als Compilerschalter mit einbauen. Dann 
kann man's aktivieren, wenn es benötigt wird. Ich denke, für komplexere 
Dinge ist sowas schon von Nöten.

StrangeMan

von Daniel R. (zerrome)


Lesenswert?

Ok, überlege ich mal wie man sowas elegant machen kann.

Du könntest ja aber einfach file.seek benutzen anstelle deiner globalen 
variable. Wie das dann mit der Geschwindigkeit aussieht müsste man mal 
sehen. ffseek() updatet dir file.seek ja auch wenn du vor oder zurück 
spulst. Kleines Beispiel:
1
for(file.seek=0;file.seek<file.length;file.seek++){
2
3
//code zum lesen...
4
//eventuell sogar ffseek() da dies ja file.seek auch updatet...
5
6
}

Grüße Daniel

von Johannes N. (strangeman)


Angehängte Dateien:

Lesenswert?

Hallo mal wieder.

Ich hab die mcc.c/mcc.h von Ulrich Radig rausgekramt und den 
Software-SPI-Modus von ihm wieder übernommen. Allerdings ... naja, es 
klappt nicht, und ich weiß nicht, obs an meiner Hardware oder am Code 
liegt. Ich hab meine Version der mcc.c mal angehängt. Eigentlich kann 
man ja nichts falsch machen. Offensichtilich aber doch...

StrangeMan

von Johannes N. (strangeman)


Angehängte Dateien:

Lesenswert?

Ohje, entschuldigt. Die Zeile, in der der Hardware-SPI eingerichtet 
wird, gehört natürlich entfernt. (nach Zeile 50: stattdessen
1
  #if SPI_Mode
2
3
    //Aktiviren des SPI - Bus, Clock = Idel LOW
4
5
    //SPI Clock teilen durch 128
6
7
    SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1); //Enable SPI, SPI in Master Mode  
8
9
  #endif
 einfügen).

Anbei auch noch meine mmc.h. Die Pins habe ich in einer anderen 
headerdatei. Sie sind
1
#define SD_INSIDE_PORT         PORTA
2
#define SD_INSIDE_PIN         PINA
3
#define SD_INSIDE_DDR         DDRA
4
#define SD_INSIDE_Pin         PA0
5
6
#define SD_WRITEPROT_PORT       PORTA
7
#define SD_WRITEPROT_PIN       PINA
8
#define SD_WRITEPROT_DDR       DDRA
9
#define SD_WRITEPROT_Pin       PA2
10
11
#define SD_PORT            PORTA
12
#define SD_P_IN            PINA
13
#define SD_DDR            DDRA  
14
15
#define SD_DI            PA3    
16
#define SD_DO            PA6    
17
#define SD_SCK            PA1  
18
#define SD_SS            PA7

Grüße,
StrangeMan

von FlipFlop (Gast)


Lesenswert?

Ich könnte mir vorstellen, dass es am Timing liegt, da überhaupt keine 
delays in der SOFT-SPI sind, vielleicht einfach mal ein paar Pausen 
einfügen.

von Johannes N. (strangeman)


Lesenswert?

Ja, danke, das klappt. Da die Routinen so bei Ulrich Radig wohl auch 
gehen, dachte ich, das wär in Ordnung so.
Damit geht's erstmal:
1
//############################################################################
2
3
//Routine zum Empfangen eines Bytes von der MMC-Karte 
4
5
unsigned char mmc_read_byte (void)
6
7
//############################################################################
8
9
{
10
  unsigned char Byte = 0;
11
#if SPI_Mode  //Routine für Hardware SPI
12
  SPDR = 0xff;
13
  while(!(SPSR & (1<<SPIF))){};
14
  Byte = SPDR;
15
16
#else      //Routine für Software SPI
17
  for (unsigned char a=8; a>0; a--) //das Byte wird Bitweise nacheinander Empangen MSB First
18
    {
19
20
    SD_PORT &=~(1<<SD_SCK); //erzeugt ein Clock Impuls (Low) 
21
    _delay_us(1);
22
    if (bit_is_set(SD_P_IN,SD_DI) > 0) //Lesen des Pegels von MMC_DI
23
        {
24
        Byte |= (1<<(a-1));
25
        }
26
      else
27
        {
28
        Byte &=~(1<<(a-1));
29
        }
30
    SD_PORT |=(1<<SD_SCK); //setzt Clock Impuls wieder auf (High)  
31
    _delay_us(1);
32
    }
33
#endif
34
  return (Byte);
35
}
36
37
38
//############################################################################
39
//Routine zum Senden eines Bytes zur MMC-Karte
40
void mmc_write_byte (unsigned char Byte)
41
//############################################################################
42
{
43
#if SPI_Mode    //Routine für Hardware SPI
44
  SPDR = Byte;   //Sendet ein Byte
45
  while(!(SPSR & (1<<SPIF))) //Wartet bis Byte gesendet wurde
46
  {
47
  }
48
#else      //Routine für Software SPI
49
  for (unsigned char a=8; a>0; a--) //das Byte wird Bitweise nacheinander Gesendet MSB First
50
  {
51
    _delay_us(1);
52
    if (bit_is_set(Byte,(a-1))>0)  //Ist Bit a in Byte gesetzt
53
        {
54
        SD_PORT |= (1<<SD_DO); //Set Output High
55
        }
56
      else
57
        {
58
        SD_PORT &= ~(1<<SD_DO); //Set Output Low
59
        }  
60
    SD_PORT &= ~(1<<SD_SCK);  //erzeugt ein Clock Impuls (LOW)
61
    _delay_us(1);
62
    SD_PORT |= (1<<SD_SCK); //setzt Clock Impuls wieder auf (High)
63
  }
64
  SD_PORT |= (1<<SD_DO);  //setzt Output wieder auf High  
65
#endif
66
}
Ob das Timing so ideal ist, sei dahingestellt. Ich werde nochmal die 
Spezifikationen anschauen, aber das mache ich später.

Danke,
StrangeMan

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Neue Version !

Überarbeitete mmc.c und Optimierung des Codes.

Jetzt auch Multiblock Operationen möglich. Wird allerdings nicht von 
allen Karten unterstützt, daher optional als define wählbar.

Neuere Doku wird nachgereicht.
Wird wie immer hier nachzulesen sein: 
http://www.mikrocontroller.net/articles/AVR_FAT32


Grüße Daniel

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

So,
hier noch die Version als AVR-Studio 4.17 Projekt.

Grüße Daniel

von Michael Z. (incunabulum)


Angehängte Dateien:

Lesenswert?

Daniel,

ich hab mir heute mal die neue Version deiner Lib zu Gemüte geführt. Wie 
auch die alten Versionen funktioniert das auf einem zur Zeit in der 
Mache befindlichen Alleskönner-Board wie geschmiert. Super Arbeit!

Und - wie bereits letztes Jahr - ich hab mal wieder ein paar Ideen, die 
die Lib noch besser machen könnten. Für mich natürlich :-)

1) Sinnvolle Rückgabewerte
Viele Methoden geben unsigned chars für Statusinformationen zurück. 
Sowas in etwa:
1
 if(2==ffopen("TEST    TXT")) { ... }
Hier würde ich mir defines wünschen, die eben diese Statusinformationen 
sprechend bezeichnen. Sowas z. B.
1
 #define MMC_FILE_NEW 2 
2
 if(MMC_FILE_NEW == ffopen("TEST    TXT")) { ... }

Gibt es eigentlich eine Doku für diese Return-Values?

2) Uart-Funktionen per Config einstellen
Das hatte ich mir ja schon oben gewünscht, da ich ansonsten jedesmall 
die Sourcen ändern muss.

3) Status-Signale der SD-Card
Bei den meisten Kartenslots kann man neben den wichtigen Pins auch 
auslesen, ob eine Karte eingelegt ist und ob diese schreibgeschützt ist. 
Wär doch schön, wenn wie die Lib von Roland Riegel, das auch 
berücksichtigt werden könnte.

Alle Config-Optionen in eine separate Config-Header-Datei geschrieben 
sieht dann so aus, wie im Anhang zu finden. Die SPI-Pins etc. ziehe ich 
mir aus einer globalen Hardware-Header für SPI. Die Defines für die 
Statusinformationen könnten wohl auch woanders hin.

cu, Michael

von Daniel R. (zerrome)


Lesenswert?

Hallo,
bin immer offen für Anregungen :)

-1.) Mich hat es Tatsache auch schon öfters genervt das man einer 2 
nicht ansieht was es genau bedeutet... werde ich ändern.

Störend ist nur, dass z.B. folgendes "define TRUE 1" 2 Byte Ram frisst 
wenn man "TRUE" irgendwo im Code nutzt. Mir war nie die Idee gekommen 
"define TRUE '1'" zu machen :) ist dann nur ein 1 Byte ...

-2.) Da fällt mit keine tolle Lösung ein, na ja mal sehn...

-3.) Ich hab so nen Kartenslot nicht, daher kann ich das schlecht 
testen, müsste mir mal so nen Slot besorgen :)

Software SPI möchte ich dann auch noch mich rein packen ins nächste 
Release.


Grüße Daniel

von Winne (Gast)


Lesenswert?

Wie wäre es "True" als Bit  anzulegen

gegebenenfalls mehrere Bitvarriablen/konstanten zu einem Byte zu fassen?

von Michael Z. (Gast)


Lesenswert?

Moin Daniel,

> Störend ist nur, dass z.B. folgendes "define TRUE 1" 2 Byte Ram frisst
> wenn man "TRUE" irgendwo im Code nutzt. Mir war nie die Idee gekommen
> "define TRUE '1'" zu machen :) ist dann nur ein 1 Byte ...

Ist dem wirklich so? Bis heute dachte ich, dass defines nur durch den 
Präprozessor verwendet zum ersetzen herangezogen werden und erst danach 
der compiler einspringt...

Zum Uart:
Für dich relevant sind ja nur 3 Infos zum Uart. Include-Statement, 
uputs, uputc. Ich (als Freund der #defines würde das dann wieder per 
config-Option lösen. Also:
1
#define UART_INCLUDE  /path/uart.h
2
#define UART_UPUTS uputs
3
#define UART_UPUTC uputc
und dann im Code die ensprechenden defines statt der echten Namen 
verwenden.

Zu 3 - Status Info:
Hier müsste man überlegen, wie weit man wirklich dies durchgängig 
implementieren will. Reicht es, wenn man entsprechende Methoden zum 
Abtesten anbietet, den eigentlichen Test aber dann den Nutzer 
durchführen lässt? Oder nur bei mmc_init()? Oder sollen alle Lese- bzw. 
Schreiboperationen jeweils isAvailable4() oder isProtected() aufrufen? 
Letzteres eher nein, so würde ich denken.

cu, Michael

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Hallo,
hier mal ein kleines Update. Der Code ist nur auf anständige Return 
Werte umgestellt. Keine Funktionalen Änderungen.

>Ist dem wirklich so?
Ich dachte immer das wenn man "#define KONSTANTE 1" macht, wird das als 
Integer behandelt bei der Erzätzung im Code durch den 
Präprozessor...deshalb hab ich die defines jetzt einfach mal alle als 
chars gemacht, kann ja nicht schaden ^^

Zum Uart, zufriedener jetzt ?

Hast Du so einen Slot und wärst eventuell bereit die Funktionen zu 
schreiben und testen? Ich nehme die dann in die Lib auf. Stimme da 
nämlich bei Deine Überlegungen zu.

@Winne
Das müsste man ja dann als struct machen, und ich weiß nicht mehr warum, 
aber das ist wohl nicht so toll...
Vielleicht weiß da ja einer warum ?!?

Grüße Daniel

von Michael Z. (incunabulum)


Lesenswert?

Moin Daniel

> hier mal ein kleines Update. Der Code ist nur auf anständige Return
> Werte umgestellt. Keine Funktionalen Änderungen.

Wunderbar. Genau so etwas meinte ich. Wie sieht es bei ffopen im 
OVERWRITE Modus aus? Wird hier auch OPENED_TO_WRITE zurückgeliefert?

> Zum Uart, zufriedener jetzt ?

Fast :-) Die Defines wie auch eine globale COnfig-Datei sind klasse. 
Fehlt nur noch, dass die Quellen mmc.c und file.c auf die neue 
uart-syntax angepasst werden :)


> Hast Du so einen Slot und wärst eventuell bereit die Funktionen zu
> schreiben und testen? Ich nehme die dann in die Lib auf. Stimme da
> nämlich bei Deine Überlegungen zu.

Ich hab so einen Slot und ja, ich könnte dies ausprobieren und 
entsprechend implementieren. Das ganze würde dann über zwei Funktionen 
in mmc.h / mmc.c implementiert werden. Nämlich:
- u08 mmc_present()
- u08 mmc_protected()

Diese kann der User nach belieben selber aufrufen. Ausserdem werden 
diese in mmc_init() mit aufgenommen. Sollte keine Karte vorhanden sein 
bzw (bei write-Funktionalität)  diese schreibgeschützt sein, so werden 
entsprechende Status-Codes zurückgeben. Das ganze wird natürlich per 
#define abschaltbar :-) Und je nachdem, ob write-Support drin ist oder 
nicht, werden nur die erforderlichen Methoden kompiliert.

Da ich nur am WoE zum Testen komme kann das ganze aber doch 2 bis max. 3 
Wochen dauern. Geht halt nicht schneller

cu, Michael

von Michael M. (mikmik)


Lesenswert?

Erstmal danke für die Lib, funkt sehr gut bei mir. Nur eines, was es 
vielleicht Anfängern erleichtern könnte:
In der mmc.h steht:

#if defined (_AVR_ATmega16_)
  #define SPI_DI    6  //Port Pin an dem Data Output der MMC/SD-Karte 
angeschlossen ist
  #define SPI_DO    5  //Port Pin an dem Data Input der MMC/SD-Karte 
angeschlossen ist
...

Der Satz "Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist 
" drückt, denk ich, das Gegenteil von dem aus, was er sagen soll. Weil 
SPI_DI ("Data in") der MOSI pin ist, also der Data Output vom Master und 
nicht von der Karte. Vice versa für SPI_DO.

Vielleicht kann man einfach MOSI/MISO/SCK/.... in die Comments 
schreiben.
Nur so als Vorschlag.
Danke nochmal,
mik

von StrangeMan (Gast)


Lesenswert?

Naja, ich dachte da ist der DataIn der Karte gemeint. Aber MOSI/MOSI 
wäre sicherlich eindeutiger.
Eine globale Configdatei würde ich auch befürworten. Ich habe sie mir 
für mein Projekt selbst angelegt, weil ich da sehr viele verschiedene 
Defines habe, die ich zentral editieren können will. Wenn man auch in 
diesem Code hier eine globale Configdatei macht, ließe sich deren 
Include-Anweisung einfach rauskommentieren um eine eigene Configdatei zu 
erwenden.

StrangeMan

von Michael M. (mikmik)


Lesenswert?

HAllo, falls es wer brauchen kann, oder vielleicht kann man es überhaupt 
in die Lib aufnehmen: habe ein file-exists geschrieben:

für die file.c
1
unsigned char ffexists( unsigned char name[]){
2
  unsigned char file_flag=fat_loadFileDataFromDir(name);    
3
  if( file_flag==0 ){return 1;}  //Datei existiert!
4
else {return 0;}
5
}

und für die file.h
1
 extern unsigned char ffexists( unsigned char name[]);

have fun,
MM

von Daniel R. (zerrome)


Lesenswert?

Hallo, zusammen.

@Michael Z. (incunabulum)
Ja wäre cool wenn du das so machst mit dem Slot. Eilt auch nicht so ...

@StrangeMan (Gast)
Die mmc-0.5.5.1.zip hat schon eine solche config.h

@ Michael M. (mikmik)
Du benutzt nicht die Version mmc-0.5.5.1.zip ?
Da ist zwar die Dokumentation in der mmc.h noch nicht auf MISO/MOSI usw 
umgestellt aber mit den defines ist es einfach übersichtlicher

Man könnte das noch etwas verkürzen:
1
unsigned char ffexists( unsigned char name[]){
2
  return fat_loadFileDataFromDir(name);    
3
}

Und als Abfrage:
1
if(TRUE==ffexists((unsigned char*)"MAIN    C  "){
2
3
   irgendwas machen
4
}

Da das ja aber eigentlich nur eine Zeile ist und man sich wenn man das 
direkt machen würde wie z.B :
1
if(TRUE==fat_loadFileDataFromDir((unsigned char*)"MAIN    C  "){
2
3
   irgendwas machen
4
}

auch eine Funktionsaufruf spart hatte ich das nicht extra geschrieben :)
Ist zwar fragwürdig ob man bei sowas sparen muss aber egal.


Grüße Daniel

von Daniel R. (zerrome)


Lesenswert?

Ach ja, was mir da noch einfällt,
wenn man im Überschreibenmodus eine Datei öffnet bekommt man auch 
OPENED_TO_READ zurück. Es gibt die Datei ja schon die man überschreiben 
möchte. Wenn man sich einmal für OVER_WRITE entschieden hat, kann man 
wild in der Datei rumschreiben...

Grüße

von Michael Z. (incunabulum)


Angehängte Dateien:

Lesenswert?

Moin Daniel,

hier also die entsprechende Erweiterung deiner Lib. Status-Pins (card 
present, card protected) werden nun berücksichtigt, so entsprechend in 
config.h aktiviert. Die wichtigen Änderungen meinerseits findest du nach 
dem Tag // mz:

Die eigentliche Konfiguration erfolgt in mmc.h unten. Dort werden die 
Pins etc. entsprechend gesetzt. Das ist fast 1:1 von Roland Riegel 
kopiert. In mmc.c sind dann die entsprechendne Methoden definiert und in 
mmc_init() eingebunden.

Anmerkungen:

0) Ich habe einige zusätzliche Return-Werte mittels Define gesetzt. Das 
macht die Lib imho lesbar. Fehlt nur noch die Doku :-)

1) FALSE sollte immer (int) 0 sein. Ansonsten ist ein Test über 
if(someBoolMethod()) nicht möglich, sondern es wird immer ein expliziter 
Vergleich if(true==...) benötigt.

2) defines: Ich habe mal alle Defines umgeändert, so dass diese immer 
als Präfix MMC_ aufweisen. Dies ist gängige Syntax, da man hierdurch im 
Code zumindest erraten kann, welches Define für was herangezogen wird. 
Oder wüsstest du, woher WRITE kommt, so diese Directive in  main() 
vorkommt?

2b) OPENED_TO_READ und OPENEND_TO_WRITE sind imho nicht ganz korrekt. 
Siehe die Problemtatik bem überschreiben. Ergo habe ich diese wieder 
unbenannt zu MMC_FILE_NEW, MMC_FILE_EXISTS. Das trifft die Tatsache 
besser, denke ich.

Comments?

cu, Michael

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ja sieht soweit gut aus.
In der SdCard.h ist das c++ ? Da steht was von namespace ?!?
Hatte jetzt noch nicht die Zeit mir alles mal genauer zu Gemüt zu 
führen, mache ich aber heute Abend.

Zu den defines,
FILE_NEW und FILE_EXISTS find ich gut.
Allerdings hast du ja jetzt alle defines in MMC_xxx umbenannt. Bringt 
also genau so viel wie gar kein Präfix, oder hab ich da was falsch 
verstanden? Außerdem gibt es defines die in allen Dateien vorkommen wie 
z.B. MMC_WRITE (alias WRITE) auf was sollte man sich da jetzt festlegen?
Werde das aber aufgreifen und mal sehen ob man das nicht noch etwas 
bessert ordnen kann.
Generell, wenn man etwas in Großbuchstaben sieht ist es ein define und 
die sind immer in der config.h, das ist doch auch schonmal was :)

Danke für die Hilfe und Mitarbeit.

Grüße Daniel

von Michael Z. (incunabulum)


Lesenswert?

Moin Daniel,

ja, da ich komplett mit C++ entwickel, ist die SdCard.h ein einfacher 
Wrapper für CPP. Das kannst du also ignorieren. Dieser packt die ganze 
MMC-Funktionen in einen eigenen Namespace und verwendet eine 
Methodenbennenung, wie ich sie sonst verwende. Also Camel-Case anstatt 
Unterstriche.

> Zu den defines,
> Allerdings hast du ja jetzt alle defines in MMC_xxx umbenannt. Bringt
> also genau so viel wie gar kein Präfix, oder hab ich da was falsch
> verstanden?

Ich glaube ja. Nem mal an, dass du zwei Libs verwendest. a) Deine MMC 
und b) eine EEPROM Lib. Beide definieren ein #define WRITE. Solltest du 
nun in main() beide Libs importieren, so hast du das Problem, dass WRITE 
aus der mmc oder der EEPROM lib kommen kann. Weiterhin kann es sein, 
dass diese auch noch mit unterschiedlichen Werten definiert ist. Und 
dann?

So, wie ich deine Lib sehe, wird das Problem nicht auftreten, da eben 
config.h nur von den mmc-headern und sourcen und nicht von "extern" 
included wird. Dennoch finde ich es für den Fall, dass dies aus 
"Dummheit" doch jemand machen sollte, eine gute Idee, die Quelle durch 
das MMC_ Präfix deutlich zu machen.

> Außerdem gibt es defines die in allen Dateien vorkommen wie
> z.B. MMC_WRITE (alias WRITE) auf was sollte man sich da jetzt festlegen?

Äh, das Präfix MMC bedeutet (imho) nicht, dass diese aus der MMC.h 
stammt, sondern dass es ein define aus deiner mmc-lib ist. So hab ich 
mir das jedenfalls gedacht :-)


> Generell, wenn man etwas in Großbuchstaben sieht ist es ein define und
> die sind immer in der config.h, das ist doch auch schonmal was :)

Jenau :)

> Danke für die Hilfe und Mitarbeit.

Ich will ja auch was :-) Nämlich die Funktionen die ich brauch und zwar 
ohne manuelles Merging bei folgenden Versionen

cu, Michael

von Matze N. (hupe123)


Lesenswert?

Hi,

ich wollte eben die neuste Version der SD-Kartenroutine ausprobieren und 
bin erschrocken!
Warum ist eine UART Routine mit in das Gefecht eingewoben worden?! Macht 
das Sinn?
Ich verpacke doch auch nich in eine UART-Routine ein I²C, nur weil ichs 
kann.
Das is doch am Thema vorbei, ober sehe ich das Falsch?

Gruß

von Daniel R. (zerrome)


Lesenswert?

Hallo,
bin immer noch nicht dazu gekommen mir alles anzusehen, aber so viel 
wurde ja auch nicht geändert...

>Warum ist eine UART Routine mit
>in das Geflecht eingewoben worden?!
>Macht das Sinn?

Wie meinst du das ?

Es sind ja in der config.h nur defines dazugekommen, mit denen man seine 
eigene uart lib einbinden kann...

Grüße Daniel

von Matze N. (hupe123)


Lesenswert?

Aber warum generell UART in einer SD-Karten-Routine?
Soll diese Routine nicht nur und ausschließlich für SD-Karten sein?
Das bläht das ding nur unnötig auf und wer eine UART überwachung haben 
will, der kann das doch auch selber, z.b. in seine main.c, schreiben. 
Ich wundere mich bloß warum in der file.c in zeile 210 plotzlich der 
dateiname ausgegeben werden soll. wenn ich an meinen UART-Pins aber 
andere bausteine angeschlossen hab als ein max232, dann kriege ich 
dadurch probleme!

deswegen: warum diese feste UART einbindung?

von Daniel R. (zerrome)


Lesenswert?

Stimmt schon, müsste nicht unbedingt rein, aber das ist als Beispiel 
gedacht.
Die meisten werden wohl den UART angeschlossen haben um sich z.B. mal 
Debug Ausgaben zu machen, oder für Bootloader.
Mach "MMC_SMALL_FS TRUE" und du bist den UART los.
Funktionen wie ffls, also anzeigen von Dateien eines Verzeichnisses, 
leben nunmal von der Ausgabe auf eine Anzeige, in diesem Fall die 
UART...

Grüße Daniel

von Matze N. (hupe123)


Lesenswert?

Naja, aber für eine allgemeingütige routine sollte sie doch so allgemein 
wie möglich gahalten sein, oder?

von Daniel R. (zerrome)


Lesenswert?

Aber wie soll man denn den Fall ffls umschiffen? Geht numnal nicht ohne 
Ausgabe. Vorschläge?

von Matze N. (hupe123)


Lesenswert?

Man könnte die Dateinamen mit der Anzahl n und die Größe in zwei Arrays 
schreiben, z.B. dateien[n*8], groesse[n] und die zwei per Pointer 
zurückgeben.
Dann kann man, wie man will, sich sie per UART, LCD oder sonstwie 
ausgeben lassen:
1
for (int i=0;i<8,i++) uart_putc(dateien[i]);
 wäre der erste dateiname
1
for (int i=11;i<19,i++) uart_putc(dateien[i]);
 wäre der zweite dateiname
usw.

die größe natürlich äquivalent.

oder man schreibt die funktion so um, daß´sie immer nur einen dateinamen 
zurück gibt, beim nächsten aufruf den zweiten, ... nachdem der letzt 
ausgegeben wurde eine NULL zurückkgibt.
Für die Dateigröße eine zweite funktion, die das selbe macht.

Damit wären die speicherfressenden arrays von meiner ersten idee 
umgangen und man kann die rückgabewerte auf LCD, UART etc ausgeben.

grußm
matze

von Matze N. (hupe123)


Lesenswert?

oh, ich wollte eben mal das sample compilieren. ich bekomme fehler:

Compiling: main_simple.c
avr-gcc -c -mmcu=atmega32 -I. -gdwarf-2   -O2 -funsigned-char 
-funsigned-bitfields -fpack-struct -fshort-enums -mcall-prologues 
-ffreestanding  -Wall -Wstrict-prototypes -Wa,-adhlns=main_simple.lst 
-std=gnu99 -DF_OSC= -MD -MP -MF .dep/main_simple.o.d  main_simple.c -o 
main_simple.o
In file included from main_simple.c:23:
SdCard.h:16: error: expected '=', ',', ';', 'asm' or '__attribute__' 
before 'SdCard'
make.exe: *** [main_simple.o] Error 1

zusätlich meckert er bei
1
uputs((unsigned char*)"\nBoot");
wenn man das
1
(unsigned char*)
 weg nimmt, klappts.

von Daniel R. (zerrome)


Lesenswert?

Ja, der  Michael Z. (incunabulum)
hat da ein paar Dinge in dem Projekt gelassen die nicht so 
funktionieren. Die "Offizielle" Version ist noch diese:

http://www.mikrocontroller.net/attachment/58218/stable-mmc-0.5.5.1.zip

bzw. für Windows Benutzer :

http://www.mikrocontroller.net/attachment/57495/AVR-Studio_stable-mmc-0.5.5.zip

Den Vorschlag die UART quasi in die main.c auszulagern, werde ich denke 
ich aufgreifen, in der nächsten Version. Wie im einzelnen muss man mal 
sehen.

von Daniel R. (zerrome)


Lesenswert?

Hm, je mehr ich darüber nachdenke je besser gefällt mir das mit dem 
auslagern der UART.

Das auslagern würde ja auch das Problem lösen, an die mitgelieferte 
uart.c/uart.h gebunden zu sein. Man könnte dann ja einfach seine eigene 
in der main.c includen...

von Matze N. (hupe123)


Lesenswert?

Genau so isses.

Mal nebenbei: die UART routine läuft auch auf meinem ATmega128 nich... 
die register heißen anders...

von Arne Z. (Gast)


Lesenswert?

Hallo Daniel,

erstmal danke für die tolle Lib von dir. Habe sie getestet, sie 
funktioniert wunderbar.
Nun hätte ich gerne eine ganz kleine Ergänzung in der mmc.h:
statt "#if defined (_AVR_ATmega32_)"
#if defined (_AVR_ATmega32_) || (_AVR_ATmega16_)
weil ich mich erst gewundert habe, wieso es zu fehlern bei meinem 
ATmega16 kam.

Weiterhin hätte ich die Frage, ob du mir sagen kannst, wieviele Zyklen 
der "ffclose()"-Befehl inklusive der Unterfunktionsaufrufe braucht. Ich 
würde das ja selber machen, leider kann ich aber mit assembler nichts 
anfangen (die Sprünge in die Unterfunktionen usw. erkenn/versteh ich 
nicht).
Die Frage habe ich, weil ich derzeit Daten auf die Karte schreibe 
(ffwrites()), und erst bei Knopfdruck den ffclose()-Befehl ausführe. 
Wenn aber die Spannungsversorgung zusammenbricht, möchte ich auch 
ffclose durchführen (damit ich die Daten auf der Karte sehe) und daher 
brauche ich die Zyklenzeit zur Berechnung meiner Kondensatoren in meinem 
Spannungsregler.

Hoffe das passt hier hin, gehört ja zu deiner Lib, aber hat halt nicht 
direkt damit zu tun.

Gruß
Arne

von Patrick (helipaddi)


Lesenswert?

Guten Morgen,

muss erstmal ein gorßes Lob an Daniel los werden, die Lib läuft bei mir 
einwandfrei! Mit den Libs von Roland Riegel etc. bin ich hingegen nicht 
zurecht gekommen...

Habe aber trotzdem noch eine Frage:
Wäre es möglich, abzufragen wie viel Speicher auf der SD Card nocht 
vorhanden ist? Werde mir gleich im Code von Roland mal ansehen wie er 
das abfragt.

Gruß,
Patrick

von Daniel R. (zerrome)


Lesenswert?

Hallo zusammen,

@ Arne Z. (Gast)
Das mit dem define, wird aufgenommen, kein Problem.

Die genaue Taktzahl ist schwer zu bestimmen, da sie von mehreren 
Parametern abhängt.
Wenn z.B. 256 Cluster am Stück frei waren und du bei ffclose alle 
beschrieben hast (aber nicht darüber hinaus !) müssen die ja noch 
verkettet werden.
Das macht dann zwei Schreiboperationen von 512 Byte Blöcken in der FAT 
aus. Dazu kommt noch das erneute Suchen der Datei im Verzeichnis, was je 
nach Größe des Verzeichnisses und Lage der Datei im Verzeichnis immer 
unterschiedlich lange dauert. Dann noch schreiben von 512 Bytes um den 
Datei Eintrag zu updaten.
Die Zeit für die Schreiboperationen ist nicht wirklich das Problem, aber 
die Zeit für das suchen von Dateien schon...
Am besten du ermittelst das Empirisch indem du einen Timer laufen lässt 
und verschiedene Szenarien durchspielst.

@Patrick Franken (helipaddi)

Ja ist möglich, man müsste ja nur alle leeren Cluster Nummern in der FAT 
zählen, diese mit der Anzahl der Sektoren/Cluster multiplizieren und 
schon hätte man das Ergebnis.

Hab momentan leider nicht so viel Zeit, aber werde ich einbauen.
Oder du schaust mal wie weit du kommst und schreibst das, dann nehme ich 
es auf :)
Die Funktion "unsigned long int fat_getNextCluster(unsigned long int 
oneCluster)" ist da dein Freund.

Spätestens nächste Woche hab ich massig Zeit.

Grüße Daniel

von Arne Z. (theich)


Lesenswert?

(nun nichtmehr Gast, sondern angemeldet)
Hallo Daniel,
danke für deine Antwort. Dann werde ich wohl mal verschiedene Szenarien 
bauen und die Zeiten überprüfen, so dass ich meinen Kondensator 
berechnen kann.

Und dann hab ich noch zwei Fragen: und zwar habe ich derzeit eine 
Funktion, die vor main() läuft, die die Datei öffnet und ans Ende geht. 
Dann wird in der main() alle 1sek bis 8 Stunden in der Datei einen 
Messwert aufgezeichnet. Erst wenn ich den Stop-Knopf drücke, wird 
ffclose ausgeführt. Gehen meine Daten verloren, wenn ich zu lange kein 
ffclose ausführe, oder aktualisiert ffclose nur das fat und verkettet? 
(also die Daten sind physisch auf der Karte, nur man sieht sie nicht)

Weiterhin gibt es eine Methode, wenn ich Daten geschrieben habe, aber 
nicht ffclose ausgeführt habe, die SD-Karte zu "reparieren", so dass 
meine Daten sichtbar werden?

Danke schonmal,
Arne

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ja die Daten sind physikalisch auf der Karte. Allerdings nur in 512 Byte 
Blöcken.

Wenn du weißt, es passiert 8 Stunden nix, wäre ein ffclose zwischendurch 
ja nicht so schlimm.

Soweit mir bekannt ist, gehen Dateisysteme davon aus, dass Cluster die 
zu einer Datei gehören immer aufsteigend gesucht werden. Daher habe ich 
es so gemacht, dass die Datei schon beim öffnen Physikalisch angelegt 
wird, also mit Dateieintrag und Startcluster. Die freien Cluster die für 
die Datei dann verkettet werden, werden ab dem Startcluster der Datei 
gesucht.
Das bietet den PC Data-Recovery Tools die Möglichkeit der Datenrettung. 
Obwohl so einmal mehr der Dateieintrag geschrieben werden muss, am Ende 
ja auch wegen der Dateigröße. Funktioniert allerdings nur zuverlässig 
bei einer Datei...

Grüße Daniel

von geb (Gast)


Lesenswert?

Hallo Daniel!
Erst mal hochachtung vor deiner Arbeit. Hab den Code für den 
ADUC7024(ARM) portiert.Nach fast 2 Wochen teilweise frustrierender 
Arbeit,Schuld sind die Arschlöcher von SD-Karten Herstellern, die keine 
vernünftigen Datenblätter herausgeben, läuft das Ganze nun einigermaßen.
Allerdings sind da 2 Punkte, die mich noch etwas beschäftigen:

1.)Nach dem Schreiben eines Sektors(Zeit: ca. 2ms) gibt die Karte 
innerhalb eines Bytes 0xE5 (Daten akzeptiert) aus.Danach geht Data out 
der SD auf 0(busy) und bleibt dort für gut 5ms.Während dieser Zeit,kann 
man keine Kommandos an die Karte senden,sondern muß warten, bis Data out 
1 wird. Damit komm ich auf einen Zyklus von ca. 7ms für 512Bytes = ca 
70KB/s.Nicht gerade berauschend.Ich hab dann noch eine SanDisk Ultra II 
2GB probiert, die ging dann mit ca. 110KB/s(busy-Phase war deutlich 
kürzer). Frage: wie kommen die Leute auf 150KB/s und mehr? Mach ich was 
falsch?

2.)Es gibt bei mir das Problem, wenn ich immer das selbe File öffne, 
Daten hinzufüge und wieder schließe,dass auf einmal falsche Sektoren 
beschrieben werden,und das File für den PC unleserlich wird. 
Interessanterweise tritt das erst bei einer Filelänge > 0x1000000 (16MB) 
auf. Mit 1x öffnen, schreiben und schließen hab ich aber auch schon 50MB 
files erzeugt,die der PC lesen konnte. Nach einem rudimentären Debug 
könnte der Fehler in ffseek liegen,kanns aber noch nicht genauer 
festmachen.
Gesehen hab ich in diesem Tread noch nichts,was auf ein solches Problem 
hinweist.Möglicherweise ist's aber auch noch nicht aufgefallen,oder ich 
hab beim portieren Mist gebaut.

Ach ja, die verwendete Version ist 5.4,die Karten sind FAT16 formatiert.

Grüße Gebhard

von Daniel R. (zerrome)


Lesenswert?

Hallo,

@ geb (Gast)
Hast du die Karte über SPI angeschlossen? Wenn ja mit welcher 
Geschwindigkeit? Ich habe hier MMC Karten (die sind meist bisschen 
schneller als SD) die machen 200KBytes/sec schreibend und 270KBytes/sec 
lesend. Das bei 10 mhz SPI Takt und im nicht  überschreiben Modus.

Bei der Version 5.4 gab es tatsächlich ein Problem in ffseek im 
Zusammenhang mehrfachem anlegen von Dateien. Nimm am besten die 5.5.1 
von hier 
http://www.mikrocontroller.net/attachment/58218/stable-mmc-0.5.5.1.zip 
,ist aber auch schwer zu sagen ob da nicht vielleicht doch auch beim 
portieren was falsch gelaufen ist. Wenn du magst, poste doch mal deine 
geänderten Routinen, dann kann man mal drüber schauen :)

So schönen Wahl Sonntag noch :)

von StrangeMan (Gast)


Lesenswert?

Hallo!

Mir ist aufgefallen, dass, wenn ich innerhalb eines Interrupts eine 
Datei öffne, sich das Programm nach dem Interrupt resetet. Komisch.
Ich hab's umgangen, indem ich einen Funktionszeiger eingerichtet habe, 
der im Interrupt auf die auszuführende Funktion (die, die die Datei 
öffnet) gesetzt wird. Das Hauptprogramm prüft in einer Endlosschleife 
verschiedene Dinge, und führt dabei immer mal diese Funktion aus. Damit 
verlagere ich dieses Öffnen ins Hauptprogramm und die Probleme sind weg.

Ich hab aber keine Ahnung, warum sich der AVR da resetet... Irgendwas 
mit dem Stack oder so? Wie gesagt, das reseten passiert am Ende der ISR.

StrangeMan

von Werner B. (werner-b)


Lesenswert?

!!!Aua!!! das tut weh!

von geb (Gast)


Lesenswert?

Hallo Daniel!

Mein Geschwindigkeitsproblem liegt an der langen busy Phase der SD 
Karte.
Reine Schreibdauer ca. 2ms/sektor, busy ca. 5ms(lt. 
Oszilloscope).Sicher,die max. 3,24Mhz SPI Takt sind auch nicht gerade 
berauschend, da hat sich Analog Device nicht gerade mit Ruhm bekleckert.

Ich werd jetzt mal die Vers. 5.5.1 portieren, und wenn das wirklich 
stabil läuft,hab ich die Idee, das fread und fwrite als Statemachine 
auszuführen und die SPI interruptgesteuert zu verwenden. Damit könnten 
diese Funktionen im Hintergrund laufen und würden nur mehr minimale 
Prozessorzeit beanspruchen(die meiste Zeit wird ja jetzt eigentlich nur 
gewartet).

Grüße Gebhard

von Arne Z. (theich)


Lesenswert?

Huhu,

Ich habe nun mal gemessen, wie lange ein ffclose() dauert. Dabei kam ich 
auf Werte zwischen
216.664 und 378.200 Takte (bei ATMega 16 @ 16MHz).
Im Durchschnitt lag ich bei 260.000 Takten (der große Wert war wohl ein 
statistischer "Ausrutscher" ^^).

Die Werte änderten sich zwar immer, aber ob die Karte nun voll war, oder 
komplett leer, hatte irgendwie keinen Einfluss.

Daniel, weißt du zufällig, ob das realistische Werte sein können?
Hast du evtl. noch eine Idee für einen "Worst Case" Fall?

Gruß
Arne

von geb (Gast)


Angehängte Dateien:

Lesenswert?

Hallo!

Hab die Vers. 5.5.1 für ADUC702x(ARM7) portiert und läuft soweit 
fehlerfrei.
Weiters hab ich in mmc.c eine Unterstützung für SDHC Karten eingebaut 
und die Schreibperformance durch verkürztes warten auf das Ende der 
"busy" Phase verbessert.
Mit den SanDisk Ultra-Karten(SD 2GB und SDHC 4GB)  kann ich jetzt doch 
150kB/s schreiben, bei 3,24 MHz SPI clock(gähn).
Ich stell mal mein mmc.c hier rein zum testen.

Grüße Gebhard

von Daniel R. (zerrome)


Lesenswert?

Hallo zusammen.

@ Arne Z. (theich)

Also ich müsste da selbst mal ein bisschen messen um das zu sehen. Nur 
rein theoretisch müsste die Zeit um eine Datei zu finden abhängig von 
der Anzahl der Dateien sein die in dem Verzeichnis sind. Je mehr Dateien 
umso länger die Such Zeit.
Sagen wir mal man kann mit 200 KBytes/s lesen, das macht dann ungefähr 
400 Sektoren und somit 6400 Datei Einträge (weil 16 pro Sektor). Ist die 
gesuchte Datei jetzt die letzte, also Datei Nummer 6400, dauert es 
mindestens 1 Sekunde um diese zu finden. Man muss die ja aber bei 
ffclose finden, um den Datei Eintrag zu updaten, das ist das Dilemma.
Bei deinen Werten habe ich raus, 0,01625 Sekunden also 16,25 ms. Ist 
jetzt zwar ne Milchmädchen Rechnung, aber das würde Pi mal Daumen so 6-7 
Sektoren bedeuten, also ungefähr 112 Dateien durchsuchen....Oder 
weniger, wenn vorher noch paar Daten Sektoren geschrieben wurden.
Mach mal ein Verzeichnis mit sagen wir 2000 Dateien (kleinen Dateien) 
und ändere dann die zuletzt drauf geschriebene ab. Da müsste sich der 
Overhead des Suchens deutlicher bemerkbar machen :)

@ geb (Gast)

Äh verkürztes warten? Kannst du dazu etwas mehr sagen, bitte.
Unterstützung für SDHC klingt auch gut. Ich werde mir deinen Code mal 
genauer anschauen :)



PS:
Hat nich mal irgendwer Lust eine FAQ auf 
http://www.mikrocontroller.net/articles/AVR_FAT32 zu machen, wo man mal 
so alle Try-and-Error-zum-Erfolg Sachen zusammen trägt? Schön wären ja 
auch alle möglichen mmc.c/mmc.h für unterschiedliche Plattformen. Bei 
mir geht nächste Woche das Semester wieder los => wenig Zeit...


Grüße Daniel

von Arne Z. (theich)


Lesenswert?

Hiho,

@Daniel,
habe nun mal 2000 Dateien im Bereich von 1-10KB auf die SD-Karte 
geschrieben, als letztes die Datei, in der ich schreiben möchte. Nun kam 
ich auf Werte von 7.645.224 bis 10.433.112 Takten.
Wow, dafür habe ich meinen Kondensator nicht ausgelegt, also darf in 
meinem Verzeichnis keine andere Datei vorhanden sein, damit ich unter 
880.000 Takten bleibe.
---
Übrigens, wenn das Semester los geht, hat man doch gerade viel Zeit, 
erst zum Ende hin wird es immer knapp (zumindest ist/war es bei mir so)
---
Gruß
Arne

von Daniel R. (zerrome)


Lesenswert?

Hallo.
Ja die Werte sehen realistisch aus, leider.
Es gibt bei Conrad 1F bis 5 Volt Goldcaps für um die 2 Euro, auch in 
kleiner Bauform. Davon ein paar und das zeug läuft Minuten lang noch :)

Wenn du jetzt 2000 Verzeichnisse mit nur einer Datei drin hast, wird das 
auch nicht besser (nur als Beispiel), eher schlechter. Große 
Betriebssysteme indizieren deshalb Dateien, um nur Indizes vergleichen 
zu müssen, wie bei Datenbanken...
Man könnte vielleicht auch das suchen etwas beschleunigen indem man z.B. 
nur den ersten Buchstaben der Datei überprüft und erst wenn der stimmt 
weitere Buchstaben. Da mach ich mir mal Gedanken dazu...

Zeit hab ich leider nie genug und dieses Semester wird noch schlimmer...

Grüße Daniel

von geb (Gast)


Lesenswert?

Noch ein spassiges Problem ist mir in Verbindung von meinem mmc.c 
aufgefallen:

Nach dem Schreiben des letzten sektors (file_Update) warte ich nicht bis 
die Karte nicht mehr busy ist.(Der Wert 0xE5 als "Daten akzeptiert" ist 
das Letzte was ich von der Karte lese.)
dieser letzte Sektor wird bei manchen Karten z.B. Kingston nicht mehr 
ins Flash geschrieben. Damit wird das fclose unwirksam und die letzten 
geschriebenen Daten (seit letztem öffnen der Datei) gehen verloren.
Offenbar brauchen diese Karten in der busy-Phase den Clock um die Daten 
aufs Flash zu speichern. Sandisk-Ultra Karten haben dieses Problem 
interessanterweise nicht.

Abhilfe: letzten sektor bei file-update 2x schreiben, oder hier extra 
busy Phase abwarten.

Grüße Gebhard

von Kai J. (tairon)


Lesenswert?

Hallo Daniel,

ich hab ein kleines Problem beim Schreiben von Daten auf SD-Karte.
Ich möchte eine Datei erstellen, Daten rein schreiben, Datei schließen.
In gewissen zeitlichen Abständen möchte ich diese Datei wieder öffnen, 
weitere Daten anhängen und Datei wieder schließen.
Beim Erstellen der Datei und beim Speichern des ersten Datensatzes 
klappt auch alles wunderbar. Will ich Datei jedoch zum Anhängen von 
weiteren Daten mit
ffstatus = ffopen(file_name);
erneut öffnen, liefert ffopen als Rückgabewert 2 (datei muss angelegt 
werden) obwohl sie bereits existiert. Die Daten werden dann auch nicht 
in die Datei geschrieben. Es sind nur die Daten des ersten 
Schreibzugriffs vorhanden.
Ich benutze die AVR-Studio Version 0.5.5

Gruß Kai

von Daniel R. (zerrome)


Lesenswert?

Hallo.

@ geb (Gast)
Man muss doch eh pollen ob die Karte busy ist oder nicht. Damit sendet 
man doch schon takte...
Orientier Dich da doch an der orginal mmc.c.

Meinst du mit file-update die Funktion flushFileData() ? Wenn ja, die 
ist nur für den internen Gebrauch in der file.c. Der User sollte die 
nicht benutzen, na ja vielleicht zu Test Zwecken...

@  Kai J. (tairon)
Das klingt seltsam. Wie sieht der String auf file_name aus?
Zeig doch mal den Code mit dem du zuerst die Datei beschreibst. Hast du 
irgendwo etwas am Code geändert?

Grüße Daniel

von Kai J. (tairon)


Lesenswert?

Hallo Daniel,

hier der Code:
erstmaliges Öffnen der Datei:
1
  unsigned char   file_name[12]="DATA    TXT";
2
3
  // SD-Karte initialisieren
4
  uart1_puts("Boot");
5
6
  while (mmc_init() !=0){       // rückgabewert 0 dann ist karte initialisiert
7
    nop();
8
  }
9
10
  uart1_puts("...");
11
12
  if(0==fat_loadFatData()){      // rückgabewert 0 dann sind die fat daten bekannt
13
14
    uart1_puts("Ok\r\n");      // wenn auf dem terminal "Boot... OK" zu lesen ist, ist init ok. jetzt kann man schreiben/lesen
15
16
  } 
17
18
  // Datei öffnen
19
  ffstatus = ffopen(file_name);
20
21
  ffwrites(data);

Nach dem Schreiben der Daten schließe ich die Datei wieder.

Um weitere Daten in der Datei zu speichern, benutze ich folgenden Code
1
  // Datei öffnen
2
  ffstatus = ffopen(file_name);
3
4
        ffwrites(data);
5
6
        ffclose();

Geändert habe ich nichts, außer dass ich meine eigene UART-Routine 
benutze, auch in file.c. Vielleicht hängts daran. das werde ich noch mal 
testen.

von Gast (Gast)


Lesenswert?

Du musst mit ffseek(file.length) ans Ende der Datei gehen.

von Kai J. (tairon)


Lesenswert?

Das hab ich gemacht. Ich bekomm aber vorher schon bei
ffstatus = ffopen(file_name);
eine 2 als Rückgabewert und nicht eine 1.
Ich schätze aber es liegt an meiner UART Routine. Ich benutze die 
Library von Peter Fleury.

von Gast (Gast)


Lesenswert?

Moin,

habe mir einen Code geschrieben, um zu sehen wie lang ein ffseek() 
(5.5.1) braucht.
Die Datei "1M.TXT" ist 10240 bytes groß, auf einer 1GB FAT32 Karte.
1
  while (second < 60) {
2
    uputc(ffopen("1M      TXT"));
3
    uputs("S");
4
    ffseek(file.length);
5
    uputs("D");
6
    ffclose();
7
  }

Beim ffseek knallts. Ich sehe das "rS", das "D" aber nicht mehr. Bei 
einer Dateigröße von 1024 bytes funktioniert der Code tadellos.

Irgendjemand eine Idee?

von Daniel R. (zerrome)


Lesenswert?

Hallo,

@ Kai J. (tairon)
Kann ich irgendwie nicht nachvollziehen wieso die Uart lib daran schuld 
sein soll. Du hast aber mindestens auch noch "#define SMALL_FILE_SYSTEM" 
geändert, sonst geht nämlich ffwrites nicht.

@ Gast (Gast)
Ok, teste ich mal. Mit wie vielen Sektoren/Cluster ist denn das 
Formatiert, damit ich gleiche Voraussetzungen habe ?

Grüße Daniel

von ffseek-Problem (Gast)


Lesenswert?

@Daniel:

Sind 8 Sektoren/Cluster. Ich habe das Problem jetzt schon auf die 
Funktion
1
void fat_getFatChainClustersInRow( unsigned long int offsetCluster)

einschränken können.

Ablauf:

file.c (ca. Zeile 163): fat_getFatChainClustersInRow(fat_getNextCluster( 
file.lastCluster )) ;

fat_getNextCluster( file.lastCluster ) klappt soweit, geht dann in 
fat_getFatChainClustersInRow() und hängt sich da irgendwo auf.

von ffseek-Problem (Gast)


Lesenswert?

In der fat_loadSector knallt's, sobald er in die if() Bedingung springt.
1
  if(sec!=fat.currentSectorNr){ // nachladen noetig
2
#if (WRITE==TRUE)
3
    if(fat.bufferDirty==1) {
4
      fat.bufferDirty=0; // buffer kann nicht dirty sein weil wird geschrieben
5
      mmc_write_sector(fat.currentSectorNr,fat.sector); // schreiben von sektor puffer
6
      //fat_writeSector(fat.currentSectorNr);
7
    }
8
#endif
9
    mmc_read_sector(sec,fat.sector);  // neuen sektor laden
10
    fat.currentSectorNr=sec; // aktualisiert sektor nummer (nummer des gepufferten sektors)
11
    return TRUE;
12
  }

Spasseshalber habe ich mir die Variable sec mal angeschaut. Im 
Fehlerfall steht in ihr irgendein Müll. Der verursacht wohl den freeze.

von geb (Gast)


Lesenswert?

@Daniel
Das ist eben der springende Punkt,in meiner mmc.c polle ich nach einem 
sektor-write nicht auf busy,sondern bereite schon die nächsten daten zum 
Schreiben vor. Auf "busy" wird dann beim nächsten write-command 
gepollt,in der Hoffnung dass das blöde Ding in der Zwischenzeit die 
Daten schon mal geflasht hat. ==>funktioniert bei Sandisk tadellos und 
erhöht die Schreibrate um 40%,bei Kingston bringts nichts(ohne CLK 
offenbar kein flashen).Schon sehr interessant, wie unterschiedlich die 
SD Karten sind.

Grüße Gebhard

von ffseek-Problem (Gast)


Lesenswert?

1
void *bytesOfSec;
in
1
unsigned long int fat_getNextCluster(unsigned long int oneCluster){

Lieg ich jetzt voll daneben, oder wo alloziierst Du Speicher für die 
Variable bytesOfSec?

von Daniel R. (zerrome)


Lesenswert?

Hm, wenn der falsche Sektor geladen wird, geht natürlich nix mehr 
(fat_loadSector).

Das ist ja keine Variable, sondern ein void Pointer, der zuerst mal auf 
nix zeigt, dann aber auf bytesOfSec=&fat.sector[j] , also auf eine 
bestimmte char Adresse im Puffer für einen Sektor.
Von dieser "Start Adresse" wird jetzt je nach FAT Typ auf 2 oder 4 Byte 
Größe gecastet.
Mit was Kompilierst du den Code? ich hab da mit dem GCC für linux und 
dem AVR-GCC keine Probleme. Kann das irgendwie nicht richtig 
reproduzieren, werde da aber mal genauere Tests machen. Bis jetzt kann 
ich leider keinen Fehler finden...



@ Gebhard
Ich glaube es ist SD Spezifikation das die Karte "CLK hörig" ist, ist 
also ein Geschenk, das es mit Sandisk funktioniert...

Grüße Daniel

von ffseek-Problem (Gast)


Lesenswert?

@Daniel:

gcc 3.4.6 AVR-CrossPack.

Ich lasse mir vor jedem return in fat_getNextCluster den Wert von 
bytesOfSec ausgeben mit:
1
    putNum(*(unsigned long int*)bytesOfSec, 'w');
Die Funktion macht nix anderes als den übergebenen Wert (unsigned long 
int) als Tausender, Hunderter etc. auszugeben. Das 'w' dient der 
Unterscheidung. Die Ausgabe schaut so aus:

w00135
w00136
w00137
w00138
w00139
w�P15
w�P15

Die letzten beiden Werte sind IMHO keine korrekten Werte.

von ffseek-Problem (Gast)


Lesenswert?

@Daniel probier das Ganze doch bitte mal mit einer 102400 byte großen 
Datei.

dd if=/dev/random of=1M.TXT bs=512 count=200

von Daniel R. (zerrome)


Lesenswert?

Joa, hab ich.
Auch mit nem image von ner Karte mit 8 Sektoren/Cluster.
Wo hast du den 3.4.6 Compiler her?

So, hab mal folgendes:

1. Mit Linux Kompiliert, Fat-resource als "/dev/mmcblk0" eingebunden und 
mit der Lib 5.5.1 getestet. Ohne Probleme.

2. Mit Linux Kompiliert und Fat-resource als Image einer Karte 
eingebunden. Mit Lib 5.5.1, ohne Probleme.

Kannst du Vielleicht ein Image der Karte machen und mir schicken, damit 
ich mit der gleichen Karte testen kann, aber anderen Kompilern usw.?

Grüße Daniel

von ffseek-Problem (Gast)


Lesenswert?

Okay, das Problem scheint nur aufzutauchen, wenn ich eine Datei lesen 
will, die am PC erstellt wurde. Wenn ich eine entsprechend große Datei 
mit der Lib generiere, ist alles ok.

von ffseek-Problem (Gast)


Lesenswert?

Der gcc war in dem AVR-GCC package für den Mac.
http://www.obdev.at/products/crosspack/index-de.html

Das ganze läuft auf nem Atmega8.

von Daniel R. (zerrome)


Lesenswert?

Das ist mal seltsam.
Ist die Datei die du dann mit der Lib erstellt hast, denn auf dem Pc 
lesbar usw.?

Was definitiv nicht geht ist eine mit Linux Formatierte Karte, da Linux 
aus welchem Grund auch immer das Root-Dir, wenn es nur 1 Cluster groß 
ist nicht mit 0xfffffff0 abschließt sondern anders.

Mein Interesse an einem Image der Karte besteht immer noch.


Grüße Daniel

von Daniel R. (zerrome)


Lesenswert?

Benutzt man zufällig auf dem Mac auch das Tool mkfs.vfat zum FAT 
formatieren?

von ffseek-Problem (Gast)


Lesenswert?

Die Datei ist am PC lesbar, ja. Der einzige Unterschied ist, dass ich 
bei einer auf dem Atmega erstellten Datei "0FFFFFFF" als bytesOfSec 
sehe, und bei der am Mac erstellten das Ganze zwei mal. D.h. die 
Funktion wird unnötigerweise nochmal aufgerufen.

Auf dem Mac macht das die GUI :).
Und die führt den Befehl newfs_msdos mit Optionen aus.

von Arne Z. (theich)


Lesenswert?

Huhu,

ich habe noch mal eine kleine Frage:
Und zwar möchte ich gerne in einer geöffneten Datei, Werte lesen und 
danach wieder ans Ende schreiben, mein Programmablauf sieht wie folgt 
aus:
ffopen(datei); -> ffseek(file.length); -> 1 bis x-mal ffwrites(werte); 
-> ffseek(file.seek+fat.cntOfBytes - (68*100)); (ist die Stelle der 
Datei, von der ich lesen möchte) -> 100-mal ffread() ->
ffseek(file.seek+fat.cntOfBytes);
Mein Problem ist nun, dass er mit dem letzten ffseek nicht an die 
richtige Stelle geht, damit ich weiter schreiben kann.
Gibt es nun eine Möglichkeit ohne ffclose() mit gefolgten ffopen(datei), 
an die richtige Stelle der Datei zu kommen, damit ich weiter 
hineinschreiben kann? Also quasi "Fat aktualisieren / file.length 
aktualisieren" ohne neue die Datei zu schließen+öffnen?

Grüße
Arne

von ffseek-Problem (Gast)


Lesenswert?

So, habe mir das Ganze nochmal genauer angeschaut. Der ffseek() hängt 
hier:

mmc.c, mmc_read_sector(...):
1
  while (mmc_read_byte() != 0xFE){};
Komischerweise bekommt er nur 0xFE zu lesen.

von Werner B. (werner-b)


Lesenswert?

ffseek-Problem schrieb:
> So, habe mir das Ganze nochmal genauer angeschaut. Der ffseek() hängt
> hier:
>
> mmc.c, mmc_read_sector(...):
>
>
1
>   while (mmc_read_byte() != 0xFE){};
2
>
> Komischerweise bekommt er nur 0xFE zu lesen.

Sieht nach Compiler bzw. Linker Problem aus.

Versuche einmal ein "make clean" und dann ein "make".

Wenn's danach immer noch nicht geht, versuche eine andere 
Toolchain/WinAVR Version.

von ffseek-Problem (Gast)


Lesenswert?

make clean bringt nichts. Habe mal gcc 4.3.2 genommen. Auch keine 
Änderung.
Ein Stack-Overflow kann es nicht sein, da die Funktion, so wie ich das 
sehe, vorher mehrfach problemlos betreten und wieder verlassen wird.

@Daniel:
Wie erstelle ich das Image der SD, und wie soll ich es Dir zukommen 
lassen?

von Daniel R. (zerrome)


Lesenswert?

Hallo zusammen.
Ich habe momentan leider echt viel um die Ohren, komme aber 
wahrscheinlich dieses Wochenende trotzdem dazu da nochmal etwas 
nachzuforschen.

@  Arne Z. (theich)

Du müsstest "#define OVER_WRITE TRUE" machen und dann zwischen schreiben 
und lesen die Dateilänge merken, damit du nach dem lesen ein seek dahin 
machen kannst.
Ungefähr so:
ffopen(datei); -> ffseek(file.length); -> 1 bis x-mal ffwrites(werte);
-> unsigned long int tmp=file.seek+fat.cntOfBytes; 
->ffseek(file.seek+fat.cntOfBytes - (68*100)); (ist die Stelle der
Datei, von der ich lesen möchte) -> 100-mal ffread() ->
ffseek(tmp);-> weiter schreiben an Dateiende.
Das müsste klappen.


@  ffseek-Problem (Gast)

Ich bräuchte als Image einfach eine Datei, in der alle Sektoren der 
Karte stehen, bzw alle Bytes. Ich mache solche Images meistens mit 
WinHex. Bei einer 1GB Karte wäre es aber wohl am besten nicht alle 
Sektoren in die Datei zu packen, sondern nur die die mit Daten belegt 
sind. Also von Sektor 0 bis zu dem letzten Sektor mit Daten...
Wie groß wird diese Datei dann bei dir? Geht die noch per Mail?

Grüße Daniel

von ffseek-problem (Gast)


Lesenswert?

@Daniel:

Ich habe die ersten 10000 Sektoren mit WinHex gebackupt. Liegen hier:
http://rapidshare.com/files/290862233/1gb_10000sect.whx.html

Sind ca. 5MB.

Danke Dir für die Mühe!

von Daniel R. (zerrome)


Lesenswert?

@ffseek-problem (Gast)

Image ist soweit Ok. Habe jetzt noch nicht auf realer Hardware getestet, 
mach ich aber gleich. Das sieht aber alles soweit Ok aus. Auf Linux mit 
dem gcc geht es problemlos, was schonmal bedeutet, das der Code an sich 
keinen Fehler verursacht.
Kann dann eigentlich nur am Compiler oder der Hardware liegen.

War die Karte auch schon so formatiert bei diesen Tests 
Beitrag "Re: MMC SD library FAT16 FAT32 read write" ?

Bei dem jetzigen Image sind die Cluster [124-148] belegt, mach in Summe 
25. Das macht bei 8 Sec/Clust 102400 Bytes. Das kommt alles hin. Die 
Cluster sind in der Fat auch richtig verkettet und Terminiert...

Grüße Daniel

von ffseek-Problem (Gast)


Lesenswert?

@ Daniel:

Ich habe auch noch ein paar Tests gemacht und folgendes festgestellt:
Es ist egal, ob ich die Karte auf einem Mac oder einem Windows Rechner
formatiere. Und es ist egal, ob die Datei als einzige auf der Karte 
existiert
oder schon andere Dateien physisch vor der Datei liegen.

Ich weiß jetzt leider nicht mehr, wie die Karte bei den Tests, die Du 
meinst, formatiert war. Es sollte aber wegen meiner vorhin beschriebenen 
Beobachtung unwichtig sein.

Ich habe inzwischen auch mal eine andere SD-Karte probiert, und das 
ganze wegen Stack-Bedenken auf einen Mega32 portiert. Immer mit dem 
gleichen Resultat.

Die Hardware möchte ich als Fehlerquelle ausschließen, da Sie nach der 
Spec von SanDisk aufgebaut ist. Ich werde als nächstes das Ganze mal mit 
WinAVR kompilieren und testen. Kannst Du mir sagen welche Version Du 
nutzt?

von ffseek-problem (Gast)


Lesenswert?

Negativ. Auch wenn ich es mit WinAVR unter Windows mache gibt es immer 
den gleichen Fehler. Habe auch auf von 8MHz auf 4MHz heruntergetaktet. 
Kein Unterschied.

von ffseek-Problem (Gast)


Lesenswert?

Vielleicht hilft Dir das noch weiter.

Im Fehlerfall ist bei FAT32:

- in der Funktion fat_getNextCluster():
i = 0x001FFFFF (2097151 dezimal)
fat.fatSec = 0x00000119 (281 dezimal)

- in der Funktion fat_loadSector(), die ja im Anschluss mit i + 
fat.fatSec aufgerufen wird
sec = 0x00200118 (2097432 dezimal)

Bei einer Speicherkarte mit 1 GB hab ich Brutto (1024  1024  1024) 
Byte / 512 (Byte / Sektor) = 2097152 Sektoren.

Wenn ich das also richtig sehe, versucht der anschließende 
mmc_read_sector() auf einen Sektor (2097432) zuzugreifen, der gar nicht 
mehr existiert, da die Speicherkarte nur 2097152 Sektoren hat.
Kann das sein?

von Daniel R. (zerrome)


Lesenswert?

Da bin ich langsam ratlos, weil mit dem Image das du hochgeladen hast 
habe ich keine Probleme. Poste doch mal bitte deinen ganzen Code.

von ffseek-Problem (Gast)


Lesenswert?

Eine Sache noch. Stimmt dein file.lastCluster? In dem Teil von file.c 
(ffseek)
1
  while( offset>=512 ){                  /** suchen des sektors in dem offset ist  **/
2
    sec++;                      // da byte nicht in diesem sektor ist, muss hochgezählt werden
3
    offset-=512;                  // ein sektor weniger in dem das byte sein kann
4
    file.seek+=512;                  // file.seek update, damit bei ffclose() die richtige file.length herauskommt
5
    fat.cntSecs-=1;                  // damit die zu lesenden/schreibenden sektoren stimmen
6
    if ( 0==fat.cntSecs ){                // es müssen mehr sektoren der datei gesucht werden
7
/* !!! HIER lass ich mit file.lastCluster ausgeben !!! */
8
      fat_getFatChainClustersInRow(fat_getNextCluster( file.lastCluster ) );  // nachladen von clustern in der chain
9
      sec=fat.startSectors;            // setzen des 1. sektors der neu geladenen, zum weitersuchen !
10
    }         
11
  }

Z.B. ist es einmal 0x01333231 = 0d20132401.

Hm, ziemlich kompliziert die ganze Sache :D.

von Daniel R. (zerrome)


Lesenswert?

Zeig mal bitte deine ganze Funktion in der du da die Datei öffnest liest 
usw...

von ffseek-Problem (Gast)


Lesenswert?

1
int main(void) {
2
  /* init fuer uart etc... */
3
4
  uputs("\r\n\r\nWaiting...\r\n");
5
6
  while (mmc_init() == FALSE) {
7
  }
8
9
  if (fat_loadFatData() == FALSE) {
10
    while (1) {
11
    }
12
  }
13
14
  mySize = 0;
15
  while (mySize < 60) {
16
    uputs("main ffopen\r\n");
17
    ffopen("1M      TXT");
18
    uputs("main ffseek\r\n");
19
    ffseek(file.length);
20
    uputs("main ffclose\r\n");
21
    ffclose();
22
    uputs("main ffclose done\r\n");
23
    mySize++;
24
  }
25
  while(1);
26
}

von Daniel R. (zerrome)


Lesenswert?

Das Problem ist, es gibt verdammt viele Möglichkeiten wie das was schief 
gehen kann. file.lastCluster wird in fat_getFatChainClustersInRow() 
gesetzt...
Wenn ich jetzt halt deine genaue Anwendung der Lib sehen könnte, hätte 
ich das Image und hätte somit alles genau so wie du. Dann wohl auch den 
gleichen Fehler.

^^ huch zu langsam ;)

von ffseek-Problem (Gast)


Lesenswert?

Achso...

AVR Memory Usage
----------------
Device: atmega8

Program:    7218 bytes (88.1% Full)
(.text + .data + .bootloader)

Data:        990 bytes (96.7% Full)
(.data + .bss + .noinit)

Sollte ich mir wegen letzterem Sorgen machen? Immerhin hatte ich das 
Problem auch bei einem Mega32, der ja 2K RAM hat.

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Sorry, aber das läuft bei mir durch.

Als Anhang die Ausgabe...

von Daniel R. (zerrome)


Lesenswert?

>Data:        990 bytes (96.7% Full)
>(.data + .bss + .noinit)

Ist schon ziemlich eng. Mach doch die Ausgaben kürzer wie z.B

> uputs("main ffclose done\r\n");

zu uputs("mcd\n"); oder so

von ffseek-Problem (Gast)


Lesenswert?

Okay, ich habe jetzt mal den kompletten Unterbau (mmc, file, fat) 
ersetzt durch den aus der 0.5.5.1 Lib. Nur die main() habe ich so 
gelassen. Keine Änderung. Ausgabe:

Waiting...
main ffopen
main ffseek

Das war's.

Program:    6182 bytes (75.5% Full)
(.text + .data + .bootloader)

Data:        686 bytes (67.0% Full)
(.data + .bss + .noinit)

von ffseek-Problem (Gast)


Lesenswert?

../mmc/fat.c: In function `fat_loadRowOfSector':
../mmc/fat.c:104: warning: left shift count >= width of type

Kommt das bei dir auch?

von siegmar (Gast)


Lesenswert?

Hi Jungs,
verfolge mit Spannung euer Problem.
Vielleicht doch ein Hardwareproblem.
Bricht eventuell die Versorgungsspg zusammen ???
Sollteste mal mit einem DSO überprüfen.
Noch viel Spaß
Gruß
Siegmar

von Daniel R. (zerrome)


Lesenswert?

Da bin ich platt. Wohnst du zufällig in der Nähe von Köln?
Die Datei ist auf jeden Fall auch vorhanden?
Lass dir mal die Rückgabewerte der Funktionen ffopen(), ffseek() und 
ffclose() anzeigen.

von Daniel R. (zerrome)


Lesenswert?

>../mmc/fat.c: In function `fat_loadRowOfSector':
>../mmc/fat.c:104: warning: left shift count >= width of type

Ja ist aber nur ein Warning und nicht so wild. Das muss so.

Was der " siegmar (Gast) " da schreibt is mir auch schonmal durch den 
Kopf gegangen. Wie ist die Stromversorgung bei der Schaltung?

von ffseek-Problem (Gast)


Lesenswert?

100nF direkt am SD-Slot, 200uF in der Nähe des µC.

von ffseek-Problem (Gast)


Lesenswert?

ffopen() sagt 'r'. ffseek ist void, zum ffclose komm ich garnicht :).
Köln ist ein schönes Stück weg :/.

von siegmar (Gast)


Lesenswert?

Du solltest messen, ob die Spg. zusammenbricht.
Diese Möglichkeit muß Du sicher ausschließen und schaue Dir auch die 
Flanken der Signale an, ob sie nicht zu rund sind.
Hardwarefehler mußt Du meßtechnisch ausschließen !!
So nun gut Nacht
Gruß
Siegmar

von Daniel R. (zerrome)


Lesenswert?

Welchen inhalt hat der Pointer "pt" beim verlassen von ffseek()?

von ffseek-Problem (Gast)


Lesenswert?

@ Siegmar
Jo, Oszi hab ich nicht. Multimeter grad mal :).

Folgendes passiert:

Waiting...
main ffopen
rmain ffseek
main ffclose
1main ffclose done
main ffopen

Dazu muss ich ein wenig ausholen. Das Ganze funktioniert mit 3V3 wie 
folgt.
5V (USB) Vcc -> 3V3 über LDO Regler.
5V (USBasp) Signale <-> 3V3 Signale über Levelshifter.
µC <-> SD über 3V3.

3V3                                 5V
µC ---- Levelshifter ---- USBasp
SD -+

Zunächst ist der Levelshifter (LS) auf HiZ, damit der USBasp die SPI 
nicht beeinflusst. Damit erfolgen die ersten 3 Zeilen der Ausgabe.
Sobald ich den LS aktiviere, erfolgt die Ausgabe der Zeilen 4 bis 6. 
ABER gleichzeitig wird der RESET des µC auf GND gezogen (hardwired mit 
LS). D.h. eigentlich würde er weitermachen, aber es kommt der Reset 
dazwischen.

Werd mal den LS loswerden und die vielen Käbelchen die hier 
herumschwirren.

Ein Königreich für ein Oszi.

Scheint also kein Softwareproblem zu sein.

Dennoch fetten Dank an Dich Daniel für die Mühe und Hilfe! Und natürlich 
für die Lib!

von Daniel R. (zerrome)


Lesenswert?

Joa, kein Problem. Ich habe ja auch Interesse daran, da Fehler zu finden 
und an der Qualität zu arbeiten :)

Falls du da weiter kommst, lass von dir hören.
Wenn mir noch was einfällt, meld ich mich auch.

Grüße Daniel

von siegmar (Gast)


Lesenswert?

Hallo,
normales Oszi würde Dir da auch nicht so sehr helfen, außer die Flanken 
betrachten.Mit einem DSO wäre es kein Problem den Fehler einzugrenzen 
bzw. auszuschließen.
Einfach mal einen Referenzaufbau verwenden, der bei Anderen 100% 
funktioniert. Daniels Aufbau z.B einfach nachbauen , damit ihr 
identische Testbedingungen habt. Die Länge der leitungen zur Karte sind 
nicht unkritisch und sollten so kurz wie möglich sein.

Wird schon klappen, bleib dran !
Bin gespannt was es war, laß es uns wissen.

Schönen Sonntsag noch
Gruß
Siegmar

von ffseek-Problem (Gast)


Lesenswert?

Aufbau ist Breadboard mit ca. 3cm langen Drähten von µC zur Karte. 
Dieser Aufbau funktioniert mit Chan's Lib tadellos. Seeks, writes, 
reads...

von Daniel R. (zerrome)


Lesenswert?

Krass, endlich kann ich nachvollziehen warum das bei dir rappelt...
Der AVR-GCC macht da was falsch !

Eigentlich sollte der bei folgender Schleife:
1
while( offset>=512 ){
2
 sec++;
3
 offset-=512;
4
 file.seek+=512;
5
 fat.cntSecs-=1;
6
 if ( 0==fat.cntSecs ){
7
  fat_getFatChainClustersInRow(fat_getNextCluster( file.lastCluster ) );
8
  sec=fat.startSectors;      
9
  }
10
}
auch bei offset==512 noch einmal durchlaufen, macht der aber nicht, das 
Programm stoppt einfach !

Wenn man das "while( offset>512 )" so macht, läuft es durch.
Da muss man mal weiter nachforschen !
Schlimmstenfalls sollte offset mit der >= Bedingung ja 0 werden, was 
auch richtig wäre.

von Daniel R. (zerrome)


Lesenswert?

Oha, glaub das ist vielleicht doch mein Fehler^^
Das muss ich erstmal nachvollziehen...

von ffseek-Problem (Gast)


Lesenswert?

Dann hab ich wohl einen Sonderfall erwischt :).

Das wär natürlich prima, wenn sich das softwareseitig beheben ließe.

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ja lässt sich ändern.
Bevor ich jetzt aber hier die Änderung poste, teste ich erstmal 
ausgiebig.

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

So der Bug is weg. Schwere Geburt^^

Der Fehler lag in einer Abfrage in ffseek. Warst da schon auf dem 
richtigen Weg.
Es konnte unter Umständen dazu kommen, das da verschiedene Grenzen 
aufeinander fallen und dieser Fall nicht abgefragt war.
In der Schleife in ffseek muss bei dem if die Bedingung erweitert 
werden...
1
if ( 0==fat.cntSecs && offset!=0){  
2
 fat_getFatChainClustersInRow(fat_getNextCluster( file.lastCluster ) );
3
 sec=fat.startSectors;
4
}

Es gibt da jetzt auch noch weitere Updates in der Lib.
Zu diesem Thema: Beitrag "Re: MMC SD library FAT16 FAT32 read write"
Was der Arne Z. da machen sollte, kann jetzt wegfallen, solange "#define 
MMC_OVER_WRITE TRUE" ist.

Es kann jetzt einfach in der main_simple.c eine eigene uart lib includet 
werden, da die funktion ffls() jetzt einen Parameter erwartet. Der 
Parameter muss ein Funktionspointer auf eine Funktion sein der Form: 
void funktionsName(unsigned char*); zum anzeigen der Daten.
Als Beispiel mit der mitgelieferten uart.c: ffls(uputs); und schon 
funktioniert das :)

@  ffseek-Problem (Gast)
Danke für deine Ausdauer und Hilfe.

Ich war nur am Zweifeln, weil ich den Fehler nicht reproduzieren 
konnte...


Grüße Daniel

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Und noch die AVR-Studio Variante.

von ffseek-Problem (Gast)


Lesenswert?

Ja hervorragend! Werde es gleich mal testen.

@Daniel
Klar, kein Thema.

von ffseek-Problem (Gast)


Lesenswert?

Einwandfrei! Vielen Dank!

PS: Habe die file.h leicht ergänzt:
1
#ifndef _FILE_H
2
3
  #define _FILE_H
4
  #include "config.h"

Sonst hat er gemeckert:

In file included from ../main.c:8:
../mmc/file.h:22: warning: parameter names (without types) in function 
declaration
../mmc/file.h:26: error: syntax error before "unsigned"

von siegmar (Gast)


Lesenswert?

Glückwunsch !!!!!!!!
Also doch ein Softwarefehler !
Komisch das Du den nicht reproduzieren konntest.

Noch einen schönen Tag
Gruß
Siegmar

von Daniel R. (zerrome)


Lesenswert?

Ja doch ein Software Fehler.

Das Problem war, bei mir war der nicht aufgetaucht, da fängt man halt an 
wo anders den Fehler zu suchen...
Ich glaube es hatte etwas damit zu tun wie ich besagte 1M.TXT, aus dem 
Image gelesen hatte.

Na ja, hat ja dann doch noch geklappt^^

Grüße Daniel

von Bernhard (Gast)


Lesenswert?

Hallo Johannes,
wie ich lese, beschäftigst Du dich ebenfalls mit dem Thema Soft-SPI und 
hast schon eine "Vorab"-Variante am laufen. Daniel möchte das in einer 
folgenden Version ja auch generell implementieren.

Ich betreibe hier einen Pollin-AVR mit einer für meine Bedürfnisse 
modifizierten Software von ROBUE. Robue hat auf der RADIG-Basis eine 
AVR-Steuerung entwickelt. Das funktioniert hier alles prächtig.

Nun möchte ich div. Daten in Tages-Files wegschreiben (Datenlogger). 
Hierfür suche ich ein integrierbares "Mini-Dos". Hier scheint gerade 
sowas zu "entstehen".

Das MMC/SD Slot (nach RADIG) hängt bei meinem AVR an Port D und 
funktioniert mit Radigs Testprogramm im Soft-SPI-Mode (mit invertiertem 
Clock-Takt). Nun fehlt nur noch die komplette DOS-Variante als 
Soft-SPI-Version. Leider bin ich beileibe kein C-Profi und nicht in der 
Lage sowas zu schreiben! Kleine Anpassungen hingegen klappen schon.

Kannst Du mir dein "lauffähiges Projekt" zu Testzwecken zukommen lassen 
(d.h. deine xxx.c und xxx.h Dateien im Bundle). Ich könnte dies mal auf 
meinem AVR laufen lassen und ggf. einige Schnipsel komplett übernehmen.
Ich arbeite hier mit WIN-AVR.

Herzlicher Gruß aus Franken
Bernhard

von Daniel R. (zerrome)


Lesenswert?

Hallo Bernhard.
Was meinst du mit:

>...integrierbares "Mini-Dos". Hier scheint gerade
>sowas zu "entstehen".

Meinst du eine Lib die Dateien so auf mmc/sd Karten schreiben kann, dass 
die auch am PC gelesen werden können?

Soft SPI sollte kein großes Ding werden. Komme ich sogar dieses 
Wochenende dazu, glaube ich zumindest mal.

Grüße Daniel

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Hallo,
Software SPI ist drin.
Es müssen 3 Dateien ausgetauscht werden,
config.h, mmc.c und mmc.h.

Grüße Daniel

von Johannes N. (strangeman)


Lesenswert?

Hallo Daniel, hallo Bernhard!

Ich hatte für meine Zwecke einfach den Soft-SPI-Code aus der von Ulrich 
Radig genommenen mmc.c wieder reinkopiert (den du, Daniel, im Laufe des 
Projekts offensichtlich entfernt hattest). Das ging aber nicht (siehe 
irgendwo weiter oben) und ich habe einige Delays einfügen müssen  - 
immer bei den clock-Flanken. Ich hatte dafür einfach _delay_us(1); 
genommen, weil es das kleinste Zeitintervall war, was mir einfiel. Diese 
Inline-Assembler-delays bekam ich damals auf die Schnelle nicht hin. 
Siehe hier: Beitrag "Re: MMC SD library FAT16 FAT32 read write"

Bei deinem Code - ich habe ihn fix im MS-NotePad überflogen - sehe ich 
gar keine Delays drin. Wenn es so klappt, dann würde mich interessieren, 
wie sicher das läuft. Bei mir ging damals mit ähnlichem (sogar fast 
gleichem) Code gar nix.

@Bernhard: Ich kann dir gerne mal das Projekt (bzw. die für dieses Thema 
relevanten Dateien - sonst wirds ganz schön viel... ^^) zukommen lassen. 
Ich bin nur leider gerade am falschen PC und komme an die Dateien nicht 
so schnell ran. Lass mir einfach mal deine Mail-Adresse zukommen.

Grüße,
Johannes Neumann

von Michael Z. (incunabulum)


Lesenswert?

Daniel, ich schon wieder :-)

Die neuen Config-Optionen wie auch die Idee, den UART als Argument zu 
übergeben, ist klasse. Damit ist die Lib schön portabel. Wunderbar & 
Danke!

Was mich allerdings wundert ist, wie du den UART-Funktionspointer 
definierst und verwendest. Das macht so nicht unbedingt Sinn... Also - 
irgendwie definiert wird der Funktor (Funktionspointer) in der Config.h. 
Hier:
1
#define MMC_PRINT_DISPLAY void(*uputs_ptr)(unsigned char*) 
2
  MMC_PRINT_DISPLAY;

Und dann z. B. in der file.c verwendet:
1
void lsRowsOfClust (MMC_PRINT_DISPLAY,unsigned long int start_sec){
2
  ...
3
  uputs_ptr(file.name);
4
  ...

Warum brauch ich hier den MMC_PRINT_DISPLAY define, wenn danach doch 
uputs_ptr direkt aufgerufen wird. Was passiert, wenn ich in der config.h 
das entsprechende define ändere?

Andere Ansatz
Warum nicht einfach so etwas:
1
lsRowsOfClust(void (*charHandler)(unsigned char c)) {
2
  ...
3
  (*charHandler)(someChar);
4
  ...

Die Methode definiert die Signatur des Funktionspointers eindeutig. 
Dieser wird in der Methode direkt verwendet. Das #define in config.h ist 
unnötig. Und so du willst, so kann dort vielleicht auch noch ein typdef 
helfen.
1
typedef void (*CharHandler) (u08);
2
3
lsRowsOfClust(CharHandler) {}

Macht das Sinn?

cu, Michael

von Daniel R. (zerrome)


Lesenswert?

Hallo Johannes,

der Code von Ulrich lief so out of the box nicht bei mir.
Ich dachte es liegt daran, das SCK nicht idle Low ist...aber wo ich so 
drüber nachdenke könnte es auch andere Gründe haben.

Für die maximal 8-10 Mhz Soft-SPI Takt der AVR sollte man eigentlich 
keine Pause in der Kommunikation brauchen. Da sind die Karten schon 
schneller.

Läuft denn http://www.mikrocontroller.net/attachment/60728/soft_spi.zip 
das bei dir ohne Probleme? Bei mir mit 5 Verschiedenen Karten schon. 
Unterschiedliche Frequenzen hab ich noch nicht ausprobiert, halt nur die 
16/20 Mhz...

von Daniel R. (zerrome)


Lesenswert?

Hallo Michael,
ja das define ist eigentlich schon überflüssig... gut fliegt beim 
nächsten mal raus.

Ja macht Sinn :)

von Michael Z. (incunabulum)


Lesenswert?

Daniel, dann bitte auch daran denken, die uputs_ptr calls durch das 
übergebene Argument der Methode zu ersetzen :-)

Nur als Hinweis, du machst das schon...

cu, Michael

von Johannes N. (strangeman)


Lesenswert?

Hallo mal wieder.

Ich habe eben versucht, die Version 0.5.6 zum Laufen zu bekommen. Dabei 
brauche ich aber leider noch einige Hilfestellungen...

Zuersteinmal musste ich bei fast allen ffxxx Funktionen die Argumente 
ändern. Denn: Seit der letzten Version, die ich hier genommen hatte, 
wurden alle string-Argumente von signed zu unsigned char geändert. Bissl 
ärgerlich finde ich, denn jetzt kann man nicht mehr
1
ffcd("ORDNER      ");
 schreiben, sondern muss das so machen:
1
ffcd((unsigned char*)"ORDNER      ");
Vielleicht kann mir nochmal jemand kurz erklären, wieso das so sein 
muss.

Desweiteren bekomme ich massenhaft warnings, die ich nicht einfach so 
ignorieren möchte:
1
...
2
In file included from main.c:39:
3
./sd/fat.c: In function 'fat_loadRowOfSector':
4
./sd/fat.c:105: warning: left shift count >= width of type
5
./sd/fat.c: In function 'fat_loadFileDataFromDir':
6
./sd/fat.c:157: warning: comparison is always false due to limited range of data type
7
./sd/fat.c:168: warning: comparison is always false due to limited range of data type
8
./sd/fat.c: In function 'fat_cd':
9
./sd/fat.c:192: warning: comparison is always false due to limited range of data type
10
./sd/fat.c: In function 'fat_loadFatData':
11
./sd/fat.c:527: warning: comparison is always false due to limited range of data type
12
In file included from main.c:40:
13
./sd/file.c: In function 'ffopen':
14
./sd/file.c:29: warning: comparison is always false due to limited range of data type
15
./sd/file.c: In function 'ffmkdir':
16
./sd/file.c:284: warning: comparison is always false due to limited range of data type
17
main.o: In function `flushFileData':
18
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:110: undefined reference to `fat_writeSector'
19
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:113: undefined reference to `fat_setClusterChain'
20
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:115: undefined reference to `fat_makeRowDataEntry'
21
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:118: undefined reference to `fat_writeSector'
22
main.o: In function `ffmkdir':
23
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:288: undefined reference to `fat_getFreeClustersInRow'
24
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:289: undefined reference to `fat_setCluster'
25
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:291: undefined reference to `fat_makeFileEntry'
26
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:301: undefined reference to `fat_writeSector'
27
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:305: undefined reference to `fat_makeRowDataEntry'
28
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:306: undefined reference to `fat_makeRowDataEntry'
29
/home/johannes/Documents/Bastelzeug/ATMega2560/sd/file.c:307: undefined reference to `fat_writeSector'
30
Kompilierung fehlgeschlagen.

Diese Vergleichswarnungen kann man so einfach nicht übergehen - immer, 
wenn ich so einen hatte, gab es arge Probleme. Was tun? Ist ein FASLE 
bzw. TRUE bei meinem avr-gcc was anderes als bei euch? Irgendwelche 
Vorzeichenprobleme oder so?
Zudem dieses komische Problem in der ffmkdir und flushFileData: Vor und 
hinter diesen Funktionen werden diese angeblichen "undefined references" 
aber nicht gemeldet: Warum also findet avr-gcc diese funktionen genau 
dort und nur innerhalb dieser Funktonen nicht und wie behebe ich das? 
Ich bin ziemlich ratlos...

Danke für Hilfe,
StrangeMan

[EDIT] Oh... ich seh gerade: Mache ich den Schalter für die 
Schreibunterstützung an, so verschwinden diese komischen 
reference-Fehler...

von Johannes N. (strangeman)


Lesenswert?

Ok, nachdem ich alle TRUEs und FALSEs durch mTRUE und mFALSE ersetzt 
hatte, gings. Wahrscheinlich hatte irgendeine der Libs, die ich sonst 
noch verwende, auch TRUE und FALSE definiert. Nur eben eines der beiden 
mit negativem Vorzeichen. Vielleicht sollte innerhalb der mmc-lib ein 
eigenes TRUE/FALSE genutzt werden, oder zumindest eine Warnung gemacht 
werden, wenn die Werte schon vorher (z.B. von einer anderen lib) 
definiert sind.

Nein, ganz ohne delays gehts bei mir nicht. Ich hatte ja oben meinen 
Code gepostet. Durch Testen bekam ich heraus, dass man jeweils das 
untere der zwei von mir eingefügten Delays in beiden Funktionen 
(read/write) entfernen kann. Eins muss aber rein.

Achso: Deine Soft-SPI Routinen gehen bei mir nicht. Kann am 
invertiert/nicht-invertiert Problem liegen oder an den (bei mir) 
mangelnden Delays. Müsste ich nochmal prüfen (mach ich später).
Könnte man vielleicht einfach in der nächsten Version noch einen 
Schalter für das Invertieren einfügen?

Grüße,
StrangeMan

von Daniel R. (zerrome)


Lesenswert?

Hallo,
1
./sd/fat.c: In function 'fat_loadRowOfSector':
2
./sd/fat.c:105: warning: left shift count >= width of type

sollte das einzige sein was kommen sollte. Und das ist Ok.

Zu dem TRUE und FALSE, vielleicht mach ich da einfach das "#ifndef" weg, 
dann sollte zumindest mal die Compiler Warnung wegen doppeltem 
definieren kommen.

Ich muss mal sehen ob ich nicht die Tage mal der SPI Geschichte auf den 
Grund gehe. Man müsste das ganze mal mit nem Logic-Analizer zerpflücken, 
hab ich aber keinen...

Grüße Daniel

von Bernhard (Gast)


Lesenswert?

Hallo Daniel, hallo Johannes,
Vielen Dank für Euere Antworten. Soeben habe ich Zeit gefunden um wieder 
mal am "Projekt" zu primeln. Habe die SOFT-SPI-Dateien ausgetauscht und 
die Pins meines ATMega in der Config angepaßt.

--> FUNKTIONIERTE AUF ANHIEB mit 3 verschiedene Karten (512MB bis 2GB 
SanDisk, Transcend, Kodak) sowohl FAT16 als auch FAT32, Super-Arbeit 
Daniel!!

Eine Frage hätte ich noch. Ich mußte im File main_simple.c die Zeile:
ffls(uputs);
auskommentieren sonst meckert der Compiler mich wie folgt an:

E:\05_06 mit Soft_spi\default/../main_simple.c:80: undefined reference 
to `ffls'
make: *** [MMC-Win.elf] Error 1
Build failed with 1 errors and 1 warnings...

Vermutlich habe ich da nochwas nicht ganz verstanden (eilt aber nicht).

Für Johannes,
vielen dank für das Angebot Johannes, hat sich nun aber erledigt da 
Daniel so schnell gearbeitet hat.

Herzlicher Gruß aus Franken
und nochmals MERCI !!
Bernhard

von Alex (Gast)


Lesenswert?

Hallo zusammen!

Bei mir läuft die Library leider noch nicht so reibungslos. Ich habe 
auch die SPI erweiterung hinzugefügt. Hat allerdings keine Abhilfe 
gebracht Ab und zu erstellt mir der Atmega leider noch kryptische Files 
obwohl das eigentlich nicht so sein sollte. Ich benutze dazu folgenden 
Quelltext :


unsigned char file_name[11]="LOG     TXT";
unsigned char new_log[18]="** New logging **";

...

if(sdiswriteable()&&sd_merker==0)//Überprüfungob Karte steckt
durchSchalter
    {
      while (mmc_init() == FALSE){
        nop();
        break;
      }
      if(TRUE==fat_loadFatData()){
        sd_merker = 1;

        ffopen(file_name);
        ffseek(file.length);
        ffwrite(0x0D);
        sd_laufer=0;
        do{
          ffwrite(new_log[sd_laufer]);
          sd_laufer++;
        }while(sd_laufer<17);0,
        ffwrite(0x0D);
      }
    }


if(!sdiswriteable() && sd_merker==1)// SD-Karte auswerfen
    {
      ffclose();
      sd_merker = 0;
    }

if(sd_merker==1)
    {
      portauslesenLAN(daten);
      ffwrites(daten);
    }


Eigentlich sollte der hier doch nur die Datei Log.txt anlegen und dort
Daten reinschreiben. Mittels sdiswriteable() wird abgefragt ob ein
Schalter umgelegt ist, damit Daten auf der SD Karte gesichert werden.
Ich benutze auch einen ungeraden Quarz (14745600 Hz) könnte das auch
daran liegen? Weiterhin benutze ich einen ATmega644.

Bin für jede Hilfe dankbar

Gruß
Alex

von ffseek-Problem (Gast)


Lesenswert?

Probier es doch einfach mal mit einem 8 MHz Quarz.

von Alex (Gast)


Lesenswert?

Habe ich leider nicht hier. Allerdings habe ich einen 16 MHz Quarz. Ich 
werde den mal ausprobieren(geht das auch?):)

Danke schonmal für die Hilfe
Alex

von Johannes N. (strangeman)


Lesenswert?

Hallo Alex!

Thema kryptische Files: Ich hatte eine Zeit lang eine 16MB-Karte 
(letztendlich waren es 12MB), die mit einer neuen Kamera geliefert 
wurde. Die hatte ein FAT12 Dateisystem (da zu klein für FAT16; das 
braucht 16MB+). Sobald ich die Schreibunterstützung aktiviert habe, 
kamen bei mir auch desöfteren kryptische Files raus, da der Code eben 
für FAT16/32 ist und bei FAT12 offensichtlich die FAT kaputtschreibt. 
Dann werden teils Daten von der Karte gelesen, die mit der 
entsprechenden Datei eigentlich nichts zu tun haben: Das sind dann die 
kryptischen Daten.
Also Achtung mit so kleinen Karten!

Ich hoffe, das kann dir weiterhelfen,
Johannes

von Daniel R. (zerrome)


Lesenswert?

Hallo,
bin mir nicht sicher, ob es einzig und alleine daran liegt, aber das
>unsigned char file_name[11]="LOG     TXT";
muss mindestens 12 Zeichen lang sein. Also:
1
unsigned char file_name[12]="LOG     TXT";
Wegen dem \0 was bei einem String noch hinten dran kommt.
Sonst sieht das auf den ersten Blick ja Ok aus was du da gepostet hast.
Besteht der Fehler immer noch, musst du ein wenig mehr über die Daten 
schreiben, und ob du noch andere Sachen verändert hast.
Wieviel Ram hat dein Controller?
Am Takt des Controllers wird es glaube ich nicht liegen...



Grüße Daniel

von Alex (Gast)


Lesenswert?

Danke schonmal für die Hilfe.

Ich benutze allerdings ein 2 Gig Karte mit Fat32. Daran sollte es 
eigentlich nicht liegen.

Das mit den 12 Zeichen anstelle von 11 habe ich auch geändert. Trotzdem 
treten immer noch die gleichen Kryptischen Dateien auf.

Anstelle die Datei zu öffnen erstellt der Mikrocontroller dann eine 
Kryptische Datei und schreibt da hinein. (Jedenfalls wird die log.txt 
Datei manchmal nicht angefasst.) Manchmal tretten auch noch andere 
Fehler auf. Z.B. kann die Datei selber nicht vom Computer gelesen 
werden. Könnte ja auch mit den Kryptischen Dateien zusammenhängen wenn 
irgendwo was auf der Karte wild geschrieben wird.

Eigenlich habe ich die Library nicht verändert. Die Daten die ich auf 
die Karte schreibe sind die Portdaten überführt in Strings (als Basis 
für das ganze benutze ich das AVR Webmodul vom Ulrich Radig 
(http://www.ulrichradig.de/home/index.php/avr/avr-webmodule).

Gibt es den eine Maximale Stringlänge die ich an ffwrites übergeben darf 
? Immoment überprüfe ich ob hier der Fehler liegt. Werde euch auf dem 
laufenden halten. Wenn euch noch was einfällt wäre ich sehr verbunden :)

Grüße Alex

von D. B. (deadbuglabs)


Lesenswert?

Sag mal wie groß dein Datensegment ist.
Formatiere die SD-Karte mal mit einem Windows-Rechner komplett (kein 
Quickformat).

von Alex (Gast)


Lesenswert?

Hallo zusammen!

Also ich habe den Fehler gefunden (die SD Karte war komplett mit windows 
formatiert; )

Aber der Fehler lag darin, dass die Funktion

void ffwrites( unsigned char *s ){
    while (*s) ffwrite(*s++);
    fat.bufferDirty=1;
  }

irgendwie die falsche länge des Strings ermittelt hat, den ich übergeben 
habe. Ich habe das abgeändert, indedm ich nun eine Feste Anzahl von 
Zeichen mittels ffwrite auf die SD Karte schreibe und es läuft.

Vielen Dank für eure Hilfe !

von Alex (Gast)


Lesenswert?

Nocheinmal Hallo :)

schon wieder der Alex :). Ich habe noch ein Problem. Ich schreibe Daten 
auf eine SD Karte. Hiernach lösche ich die Daten oder Formatiere die 
Daten mittels XP (der Löscht die Daten ja nicht richtig sondern nur die 
Fat-Entry (auch Formatieren hilft nicht wirklich)).

Nun will ich wieder auf die Datei schreiben. Aber anstelle neue Daten in 
eine Datei zu schreiben hängt der die Daten einfach an die alten Datei 
an (die durch das Löschen ja eigentlich schon gelöscht sein sollten). 
Ein generelles schreibe über alle Dateien ist allerdings auch 
unerwünscht. Gibt es eine Möglichkeit zu erkennen, ob die Datei von 
Windows gelöscht wurde und so das einfache schreiben in gelöschte 
Dateien zu verhindern?

Grüße Alex

von Daniel R. (zerrome)


Lesenswert?

Hallo,
also du Formatierst mit Windows die Karte, machst Datenträger sicher 
entfernen und dann erkennt die lib die Datei nicht als gelöscht?
Klingt seltsam!
Du könntest aber z.B. auch einfach mit der lib die Datei löschen, bevor 
du sie neu anlegst um so sicher zu gehen, das du sie wirklich neu 
anlegst...

Grüße Daniel

von FlipFlop (Gast)


Lesenswert?

http://www.sdcard.org/consumers/formatter/
damit wird die Karte auch unter windows komplett formatiert.

von Alex (Gast)


Lesenswert?

Hallo zusammen!

Also ich würde sagen das das dann nicht der Fehler ist. Selbst nachdem 
ich die SD-Karte mit dem tool formatiert habe ging es nicht. Ich habe 
allerdings immer noch Fehler. Wenn ich dem Fehler näher gekommen bin 
schreibe ich nochmal :).

Grüße
Alex

von Daniel R. (zerrome)


Lesenswert?

Hallo,
was gibt es neues an der Front, Alex?

Hab mir dieses Beitrag "Re: MMC SD library FAT16 FAT32 read write" 
Problem von dir mal durch den Kopf gehen lassen, ich wette es lag daran, 
dass du keinen String übergeben hattest sondern irgendwelche Daten.
Der Punkt ist, ffwrites() schreibt solange Daten, bis es auf '\0' alias 
0 trifft. Was ja das Ende eines Strings in c beschreibt.
Wenn in den Daten keine 0 bzw. '\0' vorkommt, wird der Ram Inhalt ab der 
Adresse es übergebenen Pointers geschrieben, bis irgendwann im Ram eine 
0 steht :)
Folge: Kryptische Datei

Poste doch mal deinen kompletten Code, dann schau ich mir das mal an.

Das Format Problem schau ich mir jetzt gleich nochmal genauer an. Bin 
mir aber sicher, dass bei Fat32 beim Formatieren außer dem Fat Bereich 
auch zumindest das Root-Dir mit gelöscht wird. Ist also nicht möglich da 
so einfach noch Reste einer Datei zu finden. Zumindest nicht in der von 
dir beschriebenen Weise.

Grüße Daniel

von Daniel R. (zerrome)


Lesenswert?

Beim Formatieren mit Fat32 und Windows XP wird der Fat Bereich gelöscht 
und natürlich auch der Root-Dir Bereich!
Somit gibt es keine Möglichkeit so einfach an die Daten zu kommen, die 
aber schon noch auf der Karte sind.

von Alex (Gast)


Lesenswert?

Nochmal der Alex,

also das Problem besteht weiterhin. Habe ich auch gedacht, dass das mit 
den Strings (oder mit der Länge der Strings) zusammenhängt. Allerdings 
Benutze ich immoment nur Quellcode der nach folgendem Schema aufgebaut 
ist also keine ffwrites(); Funktionen

while (*zwischespeicher_pointer) ffwrite(*zwischespeicher_pointer++);

Die Kryptischen Dateien sind schon weniger geworden allerdings auch noch 
nicht ganz weg. Ich Überprüfe gerade noch ein Paar Möglichkeiten. Mein 
nächster Ansatz wird sein, das ich die Zeichenlänge der Strings 
irgendwie falsch habe. :) Wenn es Funktioniert sag ich bescheit.

Eine Frage habe ich noch. Und zwar geht es schon meistens relativ gut 
aber manchmal kommt es vor das Ich Text finde (ich schreibe nur .txt 
Dateien) den ich früher auf die Karte geschrieben habe. Kann es sein das 
wenn solch ein Text bei anhängen an die Datei gefunden wird, einfach der 
Text mit angehängt wird?

Grüße
Alex

von ehem. ffseek-problem (Gast)


Lesenswert?

Hi Alex,

beschreibe doch mal wie Du die Karte hardwareseitig an den µC 
angeschlossen hast.

von Alex (Gast)


Lesenswert?

Hmm irgendwie komme ich noch nicht weiter. Ich kann ja mal die wichtigen 
Quelltextteile angeben und zeigen was nicht geht.
sd_ms ist sind hierbei Millisekunden(diese werden auch normal in die SD 
Karte geschrieben.



unsigned char new_log[18]="** New logging **\0";
unsigned char file_name[12]="LOG     TXT";
char after_str[7]="After \0";
char ms_str[4]=" ms\0";

...SD initialisieren...


while(1){

ffwrite(0x0D);
ffwrite(0x0D);
char zwischenspeicher[5];
char* zwischespeicher_pointer;

zwischespeicher_pointer  = after_str;
while (*zwischespeicher_pointer) ffwrite(*zwischespeicher_pointer++);

itoa(sd_ms, zwischenspeicher,10); // Into to ascii
zwischenspeicher[4]='\0';
zwischespeicher_pointer = zwischenspeicher;
while (*zwischespeicher_pointer)
          ffwrite(*zwischespeicher_pointer++);

zwischespeicher_pointer = ms_str;  // Text " ms\0";
while (*zwischespeicher_pointer) ffwrite(*zwischespeicher_pointer++);

}

Was in die SD-Karte geschrieben wird sieht folgendermaßen aus

After 1 ms

101

201
...

Allerdings sollte doch folgendermaßen Sachen in die SD Karte geschrieben 
werden.

After 1 ms
After 101 ms
After 201 ms

Die Frage die ich habe ist warum er nach dem ersten Durchlauf die 
Strings z.B. nicht mehr mitausgibt.

Grüße
Alex

von Alex (Gast)


Lesenswert?

Noch eine Anmerkung wenn ich

zwischespeicher_pointer  = after_str;
while (*zwischespeicher_pointer) ffwrite(*zwischespeicher_pointer++);

in

for(uint8_t i=0;i<11;i++)
  {
         ffwrite(after_str[i]);
  }


umwandel schreibt mir der ATmega alle möglichen Strings auf die SD Karte 
die eigenlich für Usart verwendet werden. Das verstehe ich auch noch 
nicht.

Gruß Alex

von Alex (Gast)


Lesenswert?

OK Problem gelöst.

Falls ich die Strings folgendermaßen auf die SD-Karte schreibe
ffwrite('A');ffwrite('f');ffwrite('t');ffwrite('e');ffwrite('r');ffwrite 
('  ');

geht es ohne Probleme. Ich weiß allerdings nicht wirklich warum :).

Danke für Eure Hilfe!

Gruß
Alex

von Johannes N. (strangeman)


Lesenswert?

Hallo Alex!

Ich hab mich jetzt nur kurz mit deinem Problem beschäftigt, aber etwas 
ist mir aufgefallen:

while (*zwischespeicher_pointer) ffwrite(*zwischespeicher_pointer++);

Da ist doch genau das selbe Problem wie in der ffwrites: Das Ding hört 
nur auf, wenn am Ziel des Pointers Null steht (Bedingung der Schleife). 
Du sagtest jedoch, dass es an diesem \0-Problem nicht liegen kann, weil 
du die ffwrites-Funktion nicht verwendest. Dein Code macht aber genau 
das selbe wie diese Funktion.

for(uint8_t i=0;i<11;i++)
  {
         ffwrite(after_str[i]);
  }

Da passiert folgendes: Du greifst auf das i-te Byte nach dem Pointer 
"after_string" zu. Da dieser aber nur 7 Byte groß ist, und du hier 11 
Bytes liest, liest der uC über das Ende von after_string hinaus. Daher 
kommt der Müll von den USART-Routinen, der eben zufällig im Speicher 
dahinter liegt.

Keine Ahnung, ob das jetzt so 100% richtig ist, ich habe selbst erst vor 
zwei Jahren angefangen mit C. Aber vielleicht hilfts ja doch. =c)

Johannes Neumann

von Alex (Gast)


Lesenswert?

Hallo Johannes

aber wie kommt es dann das auch bei

for(uint8_t i=0;i<11;i++)
  {
         ffwrite(after_str[i]);
  }

Müll rauskommt?

Ich meine der ließt ein Paar bytes rüber aber bei mir auf der SD-Karte 
stehen nachher sehr viele Strings die mehr als 3 oder 4 Byte drüber 
gehen. Das hat mich so sehr gewundert.

von Daniel R. (zerrome)


Lesenswert?

Hallo,
hab heute und morgen nicht viel Zeit...
Lass dir doch mal immer wenn du etwas schreibst, das auch anzeigen, z.B. 
über uart, vielleicht grenzt das etwas ein.

>Ich meine der ließt ein Paar bytes rüber aber bei mir auf der SD-Karte
>stehen nachher sehr viele Strings die mehr als 3 oder 4 Byte drüber
>gehen. Das hat mich so sehr gewundert.

Bist du sicher, dass nicht vielleicht auch alte strings von vorherigen 
Versuchen dort stehen?

Grüße Daniel

von Daniel R. (zerrome)


Lesenswert?

@ Alex (Gast)
Hallo,
und wie läuft es ? Neuigkeiten von der Front?

Grüße Daniel

von Alex (Gast)


Lesenswert?

Sorry das ich nicht eher zurückschreibe. Ein wenig Stressig die letzte 
Zeit :). Also die Usart hat mir die gleichen fehlerhafen Ausgaben 
gemacht. Darum denke ich das es sich nicht wirklich um ein 
Libraryproblem handelt. Es war eher ein Überlauf in einem Array.

Danke für die tatkräftige Hilfe
Alex

von bla (Gast)


Lesenswert?

Schön das du auf den Fehler gekommen bist.
Manchmal ist das echt zum verzweifeln ^^

Schönes Wochenende noch.

Grüße Daniel

von Daniel R. (zerrome)


Lesenswert?

Huch garnicht eingeloggt gewesen...

von Alex (Gast)


Lesenswert?

Ich hätte allerdings nocheinmal eine Frage:). Ist es möglich mit der 
Library auszulesen wieviel Speicherplatz noch auf der Karte frei ist 
(will nur Überprüfen ob die Karte voll ist. Lesen schreiben und löschen 
von Daten auf der Karte Funktioniert mitlerweile einwandfrei :)

Grüße Alex

von Helmut (Gast)


Lesenswert?

Hallo!
Ich nutze auch diese MMC/SD Funktionen und bin damit auch sehr 
zufrieden.
Ich möchte jetzt um Zeit zu sparen die Datei öffnen und erst beim 
Datumswechsel die Datei schliessen und eine neue Datei erstellen.
Wie kann ich nach einem Schreibvorgang die Daten auf der Karte 
aktualisieren ohne die Datei schließen und wieder öffnen zu müssen?

Viele Grüße
Helmut

von Daniel R. (zerrome)


Lesenswert?

Hallo zusammen.

@ Alex (Gast)
Schön das es jetzt funktioniert :)
Das mit dem Freien Platz ermitteln wollt ich schon immer mal einbauen, 
komme aber nicht dazu. Eigentlich müsste man ja nur die freien Cluster 
in der Fat durchgehen und zählen. Das mit Sektoren pro Cluster 
multiplizieren und fertig...

@  Helmut (Gast)
Ist es denn so zeitkritisch?
Weil eigentlich muss man ja alles, was beim schließen auch gemacht wird, 
bei einem kompletten update der Datei Daten auch machen. Es schadet ja 
übrigens auch nicht eine Datei länger geöffnet zu haben.

Grüße Daniel

von Daniel R. (zerrome)


Lesenswert?

Soo, hier mal auf die schnelle eine Funktion, die die Anzahl der freien 
Bytes bestimmt.
Es sollte aber mindestens ein Cluster frei bleiben am Ende, also nicht 
voll schreiben bis zum Anschlag ! Besser wäre sogar einfach 1 MB frei zu 
lassen...

1
unsigned long long int fat_getCntFreeBytes(void){
2
3
  unsigned long long int cnt=0;
4
  unsigned long int count=0;
5
  unsigned long int secOfFirstPartition;
6
  unsigned long int fatSz;
7
8
  if(TRUE==mmc_read_sector(0,fat.sector)){
9
10
      // bestimmen des 1. sektors der partition
11
      void *vsector=&fat.sector[454];
12
      secOfFirstPartition=*(unsigned long int*)vsector;
13
      if(secOfFirstPartition==0x6964654d){
14
        secOfFirstPartition=0;
15
      }
16
      else{
17
        mmc_read_sector(secOfFirstPartition,fat.sector);
18
      }
19
20
      // anzahl sektoren bestimmen die von einer fat belegt werden
21
      if(fat.fatType==32){
22
        vsector=&fat.sector[36];
23
        fatSz=*(unsigned long int *)vsector-1;
24
        fatSz*=128;
25
      }
26
      else{
27
        vsector=&fat.sector[22];
28
        fatSz=*(unsigned short*)vsector-1;
29
        fatSz*=256;
30
      }
31
32
      fatSz-=1;
33
      // zählen der freien cluster in der fat
34
      do{
35
        if(0==fat_getNextCluster(count)) cnt++;
36
        count++;
37
      }while(count<fatSz);
38
39
      // multiplizieren um auf bytes zu kommen
40
      cnt=cnt*(fat.secPerClust*512);
41
      return cnt;
42
  }
43
}

Grüße Daniel

von Alex (Gast)


Lesenswert?

Vielen dank für die Funktion (Ich brauche zirka 15 Sekunden zum auslesen 
des Speicherplatzes einer 2 Gig Karte. Alles läuft gut!
Gruß
Alex

von holger (Gast)


Lesenswert?

1
      // multiplizieren um auf bytes zu kommen
2
      cnt=cnt*(fat.secPerClust*512);

Und was machste mit ner leeren 8GB Karte? ;) Überlauf anzeigen?

von holger (Gast)


Lesenswert?

>Und was machste mit ner leeren 8GB Karte? ;) Überlauf anzeigen?

Ach was red ich denn da? Du benutzt ja long long int.
Aber mal im Ernst, es sollte eigentlich reichen die
Anzahl der freien kB zu ermitteln. Das spart das long long
Geraffel und benötigt weniger Code.

von Daniel R. (zerrome)


Lesenswert?

Hallo...

@ Alex (Gast)
Wow 15 Sekunden das ist lang. Hatte das garnicht auf realer Hardware 
getestet muss ich gestehen. Aber 15 Sekunden ist zu viel! Da muss ich 
mal überlegen wie das optimaler geht.

@ holger (Gast)
Ja stimmt schon, long long int auf nem AVR 8 Bit :) das muss man nicht 
unbedingt haben. Mal sehn was ich da mache...
Wegen der Code Größe ist mir das eigentlich egal, wer so was braucht 
muss halt platz haben, aber die Geschwindigkeit sollte stimmen.

Grüße Daniel

von Kurt B. (kurt)


Lesenswert?

Hallo Daniel,
was müsste man ändern, damit Dateien mit korrektem Datum/Uhrzeit 
angelegt werden?

Ansonsten gute Arbeit! Deine lib scheint die einzige zu sein, die 
wirklich schnelles schreiben auf SD-Karten ermöglicht.

Mfg,
Kurt

von Daniel R. (zerrome)


Lesenswert?

Hallo Kurt,
man müsste die Funktion "fat_makeRowDataEntry" in der fat.c dazu 
bewegen, da wo jetzt dummy werte geschrieben werden, richtige werte zu 
schreiben. Also das Datum und die Zeit. In den beiden Zeilen, die mit
1
// unnoetige felder beschreiben
kommentiert sind.
Die dummy Werte sind 0x01010101, also 4 Byte als Hex.
Wo jetzt genau Datum und Zeit steht, müsste ich selber mal genau 
nachschauen. In der Lib werden 12 Byte mit den dummy werten beschrieben, 
da irgendwo muss das hin :)

Grüße Daniel

von Kurt B. (kurt)


Lesenswert?

Hallo,
hier die Lösung:
Zuerst Datum und Uhrzeit besorgen:
1
uint32_t get_datetime()
2
{
3
  uint8_t year,month,day,hour,minute,second;
4
5
  //Die Werte von der RTC holen
6
  year = 2009 - 1980;
7
  month = 12;
8
  day = 2;
9
  hour = 11;
10
  minute = 45;
11
  second = 26 / 2;
12
13
  return (uint32_t) ((year * 33554432) | (month * 2097152) | (day * 65536) | (hour * 2048) | (minute *32) | (second * 1) );
14
}

Dann folgende Funktionen mit zusätzlichem Parameter unsigned long 
datetime ausrüsten: ffopen, ffclose, ffmkdir, flushFileData, 
fat_makeFileEntry, fat_makeRowDataEntry.

Nun fat_makeRowDataEntry abändern:
1
void fat_makeRowDataEntry(unsigned short row, unsigned char name [],unsigned char attrib,unsigned long int cluster,unsigned long int length, unsigned long datetime){
2
3
  fat.bufferDirty=1;                // puffer beschrieben, also neue daten darin(vor lesen muss geschrieben werden)
4
  
5
  row=row<<5;                    // multipliziert mit 32 um immer auf zeilen anfang zu kommen (zeile 0=0,zeile 1=32,zeile 2=62 ... zeile 15=480)  
6
7
  unsigned char i;                // byte zähler in reihe von sektor (32byte eintrag)
8
  unsigned char  *bytesOfSec=&fat.sector[row];  // zeiger auf sector bytes
9
  void *vsector;
10
11
  for(i=0;i<11;i++) *bytesOfSec++=name[i];        // namen schreiben
12
  *bytesOfSec++=attrib;                  // attrib schreiben
13
14
  *bytesOfSec++=0x01;  //reserviert
15
  *bytesOfSec++=0x01;  //erstellzeitpunkt in 10ms, von 0 bis 199
16
  
17
  //unsigned long datetime: (date_high,date_low,time_high,time_low)
18
  *bytesOfSec++=datetime;    //erstellzeitpunkt lowbyte
19
  *bytesOfSec++=datetime>>8;  //erstellzeitpunkt highbyte
20
21
  *bytesOfSec++=datetime>>16;  //erstelldatum lowbyte
22
  *bytesOfSec++=datetime>>24;  //erstelldatum highbyte
23
  
24
  *bytesOfSec++=datetime>>16;  //datum des letzten zugriffs lowbyte
25
  *bytesOfSec++=datetime>>24;  //datum des letzten zugriffs highbyte
26
  
27
  vsector=&fat.sector[row+20];
28
  *(unsigned short*)vsector=(cluster&0xffff0000)>>16;// low word  von cluster
29
30
  bytesOfSec += 2;        // 2 überspringen (für low word von cluster)
31
  *bytesOfSec++=datetime;    //zeit der letzten änderung lowbyte
32
  *bytesOfSec++=datetime>>8;  //zeit der letzten änderung highbyte
33
  
34
  *bytesOfSec++=datetime>>16;  //datum der letzten änderung lowbyte
35
  *bytesOfSec++=datetime>>24;  //datum der letzten änderung highbyte
36
  
37
  vsector=&fat.sector[row+26];
38
  *(unsigned short*)vsector=(cluster&0x0000ffff);  // high word von cluster
39
  
40
  vsector=&fat.sector[row+28];
41
  *(unsigned long int*)vsector=length;        // laenge
42
}

Natürlich sind die Werte für Erstellung, letzer Änderung und letztem 
Zugriff auf die Datei gleich. Ist das nicht gewünscht, muss man halt 
noch 2 weiter parameter übertragen.

Mfg,
Kurt

von Matze N. (hupe123)


Lesenswert?

Hi,

ich würde gerne die SD-Karte mit dem µC formatieren. Kann mir mal jemand 
weiterhelfen, wie dazu die Funktion aussehen müsste?!

Gruß,
Matze

von Daniel R. (zerrome)


Lesenswert?

Hallo,
das mit dem Formatieren ist nicht so einfach,
mach das lieber mit einem Pc :)
Man müsste die Register der Karte auslesen, um herauszufinden wieviele 
Sekoren die hat. Dann berechnen wieviele Fat Sektoren man braucht, wo 
dann das Root-Dir hin muss usw.
Dann ist immer noch die Frage ob man das so gemacht hat, dass ein 
Betriebssystem das auch lesen kann...

Grüße Daniel

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Hallo,
hier eine neue Version.
Neu ist:

- SDHC Unterstützung
- Eine Funktion die den freien Platz in Bytes ermittelt 
"fat_getFreeBytes()"
- Zeit Stempel Unterstützung beim Anlegen und ändern von 
Dateien/Ordnern,
dazu müssen 2 Funktionen mit leben gefüllt werden. "fat_getDate()" und 
"fat_getTime()" in der fat.c, dort ist auch dokumentiert wie das Format 
der Zeit und des Datums auszusehen haben.
- Kleinere Optimierungen

Viele Grüße

Daniel

Im Anhang: die Lib mit Linux Makefile

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Und noch die AvrStudio Variante

von Jens (Gast)


Lesenswert?

Hallo!
Ich hab das ausprobiert, also die neuste AVRStudio Variante. Eigentlich 
klappts prima, allerdings bekomme ich z.B. die Funktion:
ffrm( unsigned char name[])

nicht aufgerufen ... also nicht so daß der Compiler einverstanden ist. 
Ich habe u.a. versucht:
ffrm(file_name0);
Ging nicht, auch sämtlichen sinnvollen Ansätze die ich probiert habe, 
gingen nicht, woran mag das liegen, verwenden einen ATmega32

von Daniel R. (zerrome)


Lesenswert?

Hallo,
hast du in der config.h auch das gemacht?
1
#define MMC_SMALL_FILE_SYSTEM   FALSE

Grüße Daniel

von Daniel R. (zerrome)


Lesenswert?

Ein normaler Aufruf würde z.B. so aussehen:
1
unsigned char file_name[12]="TEST    TXT";
2
3
ffrm(file_name); // löscht datei mit namen test.txt

Natürlich müsste vorher die Karte und die Fat initialisiert sein...

von Tobi (Gast)


Lesenswert?

Hallo zusammen,

habe nen Mega32L, ne 4GB SDHC, und nen 3,7V Lipo.

meint ihr es gibt Probleme mit der um 0,4V zu hohen Spannung um das 
ganze prinzipiell zu betreiben?

Mfg Tobi

von Daniel R. (zerrome)


Lesenswert?

Hallo,
also ich würde dir empfehlen, einen Stepup-Wandler für die 
Versorgungsspannung zu benutzen. Der Akku wird mit der Zeit mit der 
Spannung runter gehen. Mit nem Stepup könnte man bei um die 1V 
Akkuspannung noch arbeiten. Also das ganze mit nem Stepup auf 3,3V und 
gut is.
Generell kann man mit nem SD-Kommando die Karte fragen was sie für ne 
Spannung mitmacht. 3,3 Volt machen alle, aber es geht eventuell auch 
weniger.

Grüße Daniel

von Tobi (Gast)


Lesenswert?

Hy Daniel,

also der Lipo wäre bei 1V schon lange dahin.

In einer späteren Version werde ich die Spannung sicherlich eh auf 3,3V 
stabilisieren, zumal ich in einem anderen Stromzweig eh nen Wandler auf 
3,7V->5V verbaut habe.

Mir geht es in einem ersten Versuch nur mal darum die Kommunikation 
Mega32L + SD Karte durch einen Versuchsaufbau zu testen. Dabei würde ich 
gerne erst einmal direkt alles brücken können. Wäre prinzipiell ja auch 
möglich da alles mit 3,3V versorgt werden will. Wenn ich wüsste ob die 
3,7V die SD Karte kaputt machen müsste ich nämlich für den 
Versuchsaufbau die Spannung auch schon wandeln was ich gerne für erste 
Versuche erst einmal vermeiden möchte.

mfg tobi

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ich hab keine Ahnung von Lipo Akkus :)

Bezugnehmend auf die Simplifyied SD-Spezifkation 2.0, die ich jetzt 
nochmal rausgekramt hab.

Also man übergibt der Karte mit CMD8 die Spannung in der man sie 
betreiben möchte, in dem Fall der Lib wären das 2,7-3,6 Volt. Antwortet 
die Karte korrekt, kann man diese Spannung anlegen. Nur wenn die Karte 
korrekt antwortet initialisiert die Lib die Karte.

Soviel dazu. Ob jetzt 0,1 Volt mehr tödlich für die Karte sind bezweifle 
ich mal stark ;)

Vielleicht hält sich aber auch dein Kartenhersteller nicht genau an die 
Spezifikation...

Hab aber auch schon gehört, dass Leute MMC/SD Karten einfach mit 5V 
betrieben haben, ohne das die kaputt gegangen wären. In der Regel sind 
das ja alles werte, unter denen das dann garantiert läuft...

Grüße Daniel

von Tobi (Gast)


Lesenswert?

Genau diese Angaben mit 2,7-3,6V habe ich auch in meiner SD 
Spezifikation.
Das mit dem CMD8 wusste ich noch nicht. Allgemein vermisse ich irgendwie 
eine Zusammenfassung der gazen Commands. Zwar sind auch einzelne 
Commands in der SPezifikation, jedoch irgendwie etwas unübersichtlich.

Ich vermute auch das 0,1V mehr nicht viel ausmacht. Hatte gehofft hier 
Erfahrungsberichte zu finden, da sich grundsätzlich ein Lipo von der 
Spannung her ja anbietet und ich ja sicher ned der erste bin der so 
einen verwendet :)

Das mit den 5V wäre ja schonmal beruhigend zu wissen, da hätte ich nicht 
gedacht das das die Karte lange mitmacht.

Ansonsten ist ja auch kein Vermögen zerstört wenn so eine Karte hops 
geht :)

Ich denke ich werds einfach mal probieren, wenn ich einen Kartenleser 
auftreiben kann der meine Karte liest um herauszufinden ob die Karte 
schon formatiert ist oder dies noch tun muss.

Danke für deine Ausführungen.

MfG Tobi

von Alex (Gast)


Lesenswert?

Hallo zusammen!

Ich habe mal ne Frage bezüglich einer Abfrage ob eine Datei schon 
existiert. Und zwar will ich überprüfen ob eine Datei mit einem Namen 
schon in dem Verzeichniss existiert. Ist so etwas möglich?

Grüße
Alex

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ja geht ganz einfach.
1
unsigned char file_flag=fat_loadFileDataFromDir(name);

"file_flag" ist jetzt TRUE wenn die Datei schon existiert oder FALSE 
wenn eben nicht. Nach dem Aufruf von "fat_loadFileDataFromDir(name)" 
sind sogar alle möglichen Daten über die Datei schon bekannt, wenn die 
Datei existiert...

Siehe auch "ffopen()" in der file.c


Grüße Daniel

von Alex (Gast)


Lesenswert?

Danke schon für die tatkräftige Hilfe! ich habe auch noch eine weitere 
Frage. Und zwar kann man auslesen wie groß der gesamte Speicherplatz der 
Fat ist?

Gruß
Alex

von Daniel R. (zerrome)


Lesenswert?

Ich denke du meinst wieviele Sektoren von der Fat belegt werden?
Das ist schon schwieriger.
1
unsigned long int fatSz;
2
3
4
  mmc_read_sector(0,fat.sector);
5
6
  void *vsector=&fat.sector[454];
7
  fatSz=*(unsigned long int*)vsector;
8
  if(fatSz==0x6964654d){
9
    fatSz=0;
10
    }
11
  else{
12
    mmc_read_sector(fatSz,fat.sector);
13
    }
14
15
16
  if(fat.fatType==32){
17
    vsector=&fat.sector[36];
18
    fatSz=(*(unsigned long int *)vsector)-1;
19
    fatSz*=128;
20
    }
21
  else{
22
    vsector=&fat.sector[22];
23
    fatSz=(*(unsigned short*)vsector)-1;
24
    fatSz*=256;
25
  }

Jetzt ist auf der Variable "fatSz" die Anzahl der Sektoren gespeichert, 
die eine bzw. die erste Fat belegt. Der erste Sektor, also ab wo die Fat 
los geht steht auf der Variable "fat.fatSec".

Der hier gepostete Code ist aus der Funktion "fat_getFreeBytes()" aus 
der fat.c...

Grüße Daniel

von Alex (Gast)


Lesenswert?

Danke dir! Aber eigentlich meinte ich die Anzahl der Bytes :). Aber das 
war doch Anz. Der Sektoren * 512 oder? Kann auch sein das ich mich da 
irre.

Gruß Alex

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ja Anzahl der Sektoren * 512.

Ich weiß ja nicht was du vor hast, aber zur Sicherheit solltest du evtl. 
noch einen Sektor dazu zählen wenn du irgendwas nach der Fat machen 
möchtest.
Falls es irgendwas mit der Fat ist wird da schon ein Sektor abgezogen, 
um auf garkeinen Fall über das Ende der Fat hinaus zu kommen.

Upps, ich seh grad da bekommst du die Cluster Anzahl raus die in einer 
Fat stehen. Bei dem Code oben muss einmal das "fatSz*=128;" und das 
"fatSz*=256;" weg !

Also so:
1
unsigned long int fatSz;
2
3
4
  mmc_read_sector(0,fat.sector);
5
6
  void *vsector=&fat.sector[454];
7
  fatSz=*(unsigned long int*)vsector;
8
  if(fatSz==0x6964654d){
9
    fatSz=0;
10
    }
11
  else{
12
    mmc_read_sector(fatSz,fat.sector);
13
    }
14
15
16
  if(fat.fatType==32){
17
    vsector=&fat.sector[36];
18
    fatSz=(*(unsigned long int *)vsector)-1;
19
    }
20
  else{
21
    vsector=&fat.sector[22];
22
    fatSz=(*(unsigned short*)vsector)-1;
23
  }




Grüße Daniel

von Matze N. (hupe123)


Lesenswert?

Hi,

ich habe grad ein verzwickes Problem.
Ich würde gerne in eine Datei, die schon einen Text enthält, Text 
einfügen.
BSP:

aus:
    "Hallo, dieser text steht schon drin."

soll:
    "Hallo, dieser text steht schon 1234567890 drin."

werden.

Man könnte jetzt natürliche den restlichen Text überscheiben und neu 
schreiben. Aber das geht nicht, da der Text hinter dem, was eingefügt 
werden soll mehrere MB groß ist und zum Auslagern fehlt mir zum einen 
der Platz und zum anderen die Zeit...

Gibts dafür eine Lösung?!

Gruß,
Matze

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Hallo,
nein dafür gibt es so noch keine Lösung.

Man müsste Prinzipiell wie in dem an gehangenen Bild vorgehen.
Allerdings müsste das noch weiter verallgemeinert werden.
Also auf Cluster anstelle von 512 Byte Sektoren und auf größere 
einzufügende Sektoren/Cluster.
Mal sehen wie sich das optimal einbauen lässt.
Da komme ich aber auch wohl erst in 2 Wochen dazu, wird auch nicht so 
einfach werden, da das ziemlich tief in die Sektor/Cluster Verwaltung 
eingreift.

Grüße Daniel

von Matze N. (hupe123)


Angehängte Dateien:

Lesenswert?

müsste das nich so sein... ich meine, man will ja evtl mehr als 512 byte 
einfügen. außerdem müsste es zwischen zwei blöcken geschrieben werden.
dein zeichnung würde "ersetzen mit einem anderen sector" bedeuten.
aber sonst meinen wir das selbe! und cool, daß du das machen willst, ich 
steige da nämlich nicht so richtig durch...!

gruß und danke schon mal,
matze :)

von Daniel R. (zerrome)


Lesenswert?

Hallo,
hm wo ich so darüber nachdenke, könnte das übler werden als ich dachte. 
Wenn man nicht genau 512 Bytes dazu macht, oder ein ganzes vielfaches 
davon, läuft das wohl doch auf ein wildes kopieren hinaus. Man hat 
irgendwie immer ein paar Bytes über...
Muss ich mal in Ruhe darüber nachdenken.

Grüße Daniel

von Matze N. (hupe123)


Lesenswert?

naja, ob das so weit gehen muss?! Ja, ok, schön wäre es, jedes Bit auf 
der Karte auszunutzen, aber sein wir doch mal ehrlich, wer Datenmengen 
kleiner als 512 Byte schreiben will, schreibt eh nur Text und der ist eh 
meistens kurz. von daher verschenk man nur wenig, selbst wenn man nur 1 
Byte / Sector schreibt.
Auf der anderen Seite: wenn man, so wie ich das Plane, ca. 175.000 
Einfügevorgänge machen wird, ist schon eine ganze Ecke an verschwendetem 
Speicherplatz (ich habs mal überschalgen: etwas mehr als 80MB - wenn ich 
mich nicht verrechnet habe).
Jedoch, bei der verfügbaren Kapazität heutiger Speicherkarten auch nicht 
mehr so viel... :)

Mach dir also nich so einen Kopf drüber. Die Abfrage, welcher Sektor 
wieviele Bytes noch übrig hat, ist, denke ich, unnötig und 
wahrscheinlich eh viel zu langsam - bzw. wenn man es in eine Variable 
schreibt, viel zu Speicheraufwendig (bei knapp 4,2 mio Sektoren auf 
einer 2GB Speicherkarte)

Grüße,
Matze

von Alex (Gast)


Lesenswert?

Danke für die hilfe :)

aber leider Funktioniert das noch nicht so wirklich. Ich überprüfe z.B. 
die Größe einer Fat auf einer 2 Gig SD Karte. Die Fat hat die volle 
Größe.
Der Quelltext den du oben geschrieben hast also gibt mir für fatSz 3742 
zurück.

unsigned long int fatSz;

  mmc_read_sector(0,fat.sector);

  void *vsector=&fat.sector[454];
  fatSz=*(unsigned long int*)vsector;
  if(fatSz==0x6964654d){
    fatSz=0;
    }
  else{
    mmc_read_sector(fatSz,fat.sector);
    }


  if(fat.fatType==32){
    vsector=&fat.sector[36];
    fatSz=(*(unsigned long int *)vsector)-1;
    }
  else{
    vsector=&fat.sector[22];
    fatSz=(*(unsigned short*)vsector)-1;
  }

Noch einen vorschlag ?  (Fehlt hier vielleicht noch ne multiplikation 
oder soetwas ?

Gruß Alex

von Daniel R. (zerrome)


Lesenswert?

Hallo,
Auszug aus der fatgen103:
1
[BPB_FATSz32 (byte) 36 (bytes) 4]
2
3
This field is only defined for FAT32 media and does not exist on
4
FAT12 and FAT16 media. This field is the FAT32 32-bit count of
5
sectors occupied by ONE FAT. BPB_FATSz16 must be 0.

,das korrespondiert mit der Prüfung:
1
if(fat.fatType==32){
2
    vsector=&fat.sector[36];
3
    fatSz=(*(unsigned long int *)vsector)-1;
4
    }

jetzt sollte auf der Variablen fatSz laut Spezifikation die Anzahl der 
Sektoren stehen die von einer Fat belegt werden. Wenn du ja genauer 
schreiben würdest wozu du das überhaupt brauchst könnte ich da 
vielleicht auch mehr zu sagen :)
Wenn du jetzt die Anzahl der Bytes haben willst musst du deine 3742 ja 
noch mit 512 Multiplizieren.

Grüße Daniel

von Alex (Gast)


Lesenswert?

Hallo Daniel,

also das passt nicht wirklich. Die Partition ist 2 Gig groß und 3742 * 
512 hat einen Wert von unter 1 MB. Was ich machen will ist, eine 
durchnummerierung von Dateien. Quasi bei 1 Anfangen ...dann 2 dann 3. 
Jede Datei ist hierbei 1 MB groß. Falls ich nun am Ende der Fat 
angekommen bin. Also bei ner 2 Gig Platte zirka bei guten 2000 dann soll 
der wieder von vorne anfangen und die erste überschreiben. Das klappt 
auch eigentlich schon recht gut wenn ich das ganze mit einer statischen 
größe mache, besser wäre das aber wenn ich das mit verschiedenen Karten 
machen könnte die jeweils eine andere Größe haben. Aber danke schonmal 
danke für die Tatkrääftige unterstüzung
Gruß
Alex

von Daniel R. (zerrome)


Lesenswert?

Aha,
da musst du anders ran gehen.

Auf FatSz steht jetzt die Anzahl der Sektoren die eine Fat belegt.
In einem Sektor der von der Fat belegt wird, können 128 Cluster 
"Adressiert" werden.
Wenn man jetzt fat.secPerClust*512 rechnet, bekommt man die Anzahl der 
Bytes die einem Cluster zugeordnet werden.
Die Anzahl der Sektoren die zu einem Cluster zusammengefasst werden ist 
immer eine 2er Potenz. Wahrscheinlich bei einer 2Gb Karte 4 oder 8. 
Damit ist die kleinste Zuordnung 2048 oder 4096 Bytes groß.

Damit solltest du jetzt rechnen können :)

Also:

FatSz*128 = Anzahl Cluster auf der Karte

512 * fat.secPerClust = Bytes in einem Cluster

1MByte / Bytes in einem Cluster = nötige Cluster Anzahl, für die 1 MByte

Anzahl Cluster auf der Karte / nötige Cluster Anzahl für die 1 MByte = 
Maximale Anzahl der der 1 MByte Dateien

Stimmst du dem zu? Könnte mich auch verrechnet haben, war jetzt nur so 
auf die schnelle...Man müsste auch mal schauen wie man rundet um da 
überall save zu sein ;)


Grüße Daniel

von Alex (Gast)


Lesenswert?

Das mit den Bytes auf der Fat werde ich die Tage mal ausprobieren und 
dir ein Feedbag geben :). Ich habe allerdings immoment auch noch ein 
ganz anderes Problem. Ich habe folgenden Quellcode

unsigned long int sd_ausgabe_zaehler;
filenamelan = 1;
char ordner[13];
ordnerName(filenamelan,ordner);
ffcdLower();
if(TRUE == ffcd("1           ")...//--> Gibt true zurück
char zwischenspeicher[5];  // Zwischenspeicher für die Umwandlung
itoa(filenamelan, zwischenspeicher,10);
char dateiname[12]="        CSV";
for(uint8_t i=0;i<strlen(zwischenspeicher);i++)//)i<=3;i++)
{
  dateiname[i]=zwischenspeicher[i];
}
if(MMC_FILE_EXISTS==ffopen((unsigned char *)dateiname))  // --> Datei 
exist
sd_ausgabe_zaehler=file.length;

char zwischenspeicher3[10];
ultoa(sd_ausgabe_zaehler,zwischenspeicher3,10);
ausgabe(zwischenspeicher3);    // Hier gibt er ziemlich große Zahlen aus


Das Problem was ichhabe ist das mit file.length für 10 kB Dateien zum 
Beispiel den Wert 640000000 zurückgibt, was ja nicht kann. Sieht jemand 
warum der das macht und nicht wie erwartet 104800 irgendwas an Bytes 
zurückgibt?

Grüße
Alex

von Alex (Gast)


Lesenswert?

ok die letzte Frage hat sich erledigt :) War ein Fehler meinerseits

Grüße
Alex

von Alex G. (almalex)


Lesenswert?

hi
ich hätte eine frage zu deinem code
ich bekomme über die serielle schnittstelle strings mit der länge von 
2048 zeichen und würde nun gerne wissen wie das geht das ich diese 2048 
zeichen dann schreibe
wenn ich nur 512 zeichen lange  Blöcke bekomme geht es wunderbar
hoffe du kannst mir helfen

danke und mfg alex

von Daniel R. (zerrome)


Lesenswert?

Hallo,
du könntest eine Ringpuffer machen. Dessen Größe müsstest du dann noch 
ermitteln, damit da nichts schief geht. So könnten dann schonmal 512 
Bytes geschrieben werden, während noch weitere abgeholt werden (falls du 
einen Interrupt zum abholen der Daten benutzt).
Siehe auch: 
http://de.wikipedia.org/wiki/Warteschlange_(Datenstruktur)#Implementierung_als_Ringpuffer

Das es nicht klappt könnte auch daran liegen, dass du die Schnittstelle 
ohne Flow-Control verwendest, vermute ich mal.
Während die Daten auf die Karte geschrieben werden kommen ja über die 
serielle Schnittstelle neue Daten an die werden aber wohl nicht abgeholt 
während die Lib noch Daten auf die Karte schreibt. Das schreiben der 
Daten auf die Karte benötigt ja eine gewisse Zeit.

Falls dir das nicht weiterhilft, könntest du mal etwas Code Posten, 
damit könnte man sich einen besseren Überblick verschaffen.

Viele Grüße

Daniel

von Alex G. (almalex)


Lesenswert?

ich hätte mir vorgestellt das ich die 2048 zeichen was ich als einen 
string bekomme auf mehrere kleine strings mit 256 zeichen oder so 
aufteile und dann schreibe. wäre das prinzipell möglich?

von Daniel R. (zerrome)


Lesenswert?

Besser immer 512er Blöcke. Es werden nämlich immer 512 Bytes von der Lib 
gepuffert bevor diese geschrieben werden.

von Alex (Gast)


Lesenswert?

Hallo,
so bin zu der Berechnug der Anzahl von Dateien gekommen. Habe das wie 
folgt gemacht :

uint32_t anzahlDateienerrechnen(uint32_t size)
{
  uint32_t anz_Cluster_Karte = size * 128;
  uint32_t byte_pro_Cluster = 512 * fat.secPerClust;
  uint32_t noetige_Cluster_fuer_1_MB = 1048576/byte_pro_Cluster;
  uint32_t anz_Dat = anz_Cluster_Karte/noetige_Cluster_fuer_1_MB;
  return (anz_Dat);
}

Mit
size = fatSz kommt die Richtige Anzahl an 1 MB Dateien raus.

Danke für die Hilfe (fatSz muss man ja vorher berechnen) Aber da ist ja 
schon oben der Quelltext angegeben.
Grüße
Alex

von Alex G. (almalex)


Lesenswert?

hi ich wenn ich einen block mit 512 byts schreiben will. geht das bei 
mir nicht und es kommt auf der seriellen schnittstelle ein neues boot. 
was kann da sein
ich lese die 512 byts über die serielle schnittstelle ein. ich kann 
maximal 256 byts auf einmal schreiben mit deinem code

von Daniel R. (zerrome)


Lesenswert?

Hallo zusammen.

@ Alex (Gast), schön das es jetzt klappt :)

@ Alex Glaser (almalex) ,welchen Mikrocontroller benutzt du denn? Wenn 
da erneut "Boot..." steht vermute ich mal einen Reset wegen Ramknappheit 
?!? Poste doch mal ein bisschen Code, damit man sehen kann was du da 
genau machst und wie du das machst. Am besten sogar den ganzen Code.

Grüße Daniel

von Alex G. (almalex)


Lesenswert?

hab das problem schon gfunden. habe ein bit zuviel gesendet und dadruch 
hat der buffer nicht gepasst. verwende einen 644 aber trotzdem danke
jetzt wende ich mich dem problem das ich einen string von 2048 zeichen 
empfangen will und denn dann schreiben will und dann einen bit zurück 
senden will wann der nächste gesendet werden soll

von Juergen (Gast)


Lesenswert?

Hallo Daniel,
ich habe noch einen kleinen Fehler in der Funktion
fat_getFreeBytes() gefunden.
Dort wird mit mmc_read_sector(0,fat.sector)
der erste Sektor der Karte in den Buffer gelesen, ohne dass
fat.currentSectorNr dadurch verändert wird.
Später wird mit
fat_getNextCluster(count) der sektor gelesen. Wenn 'count' jetzt 
identisch mit 'fat.currentSectorNr'ist(was durchaus vorkommt) wird der 
Sektor nicht in
den Buffer gelesen.

meiner Meinung nach müsste es ausreichen wenn man Sektor 0 nicht mit
mmc_read_sector(0,fat.sector) liest sondern statt dessen
fat_loadSektor(0) verwendet.

Kannst du dir ja noch mal anschauen.

Grüße
Jürgen

von Alex G. (almalex)


Angehängte Dateien:

Lesenswert?

Hi
ich hab ne frage
ich habe es jetzt geschafft 2048 Zeichen auf die SD karte zu schreiben 
wenn ich die daten über die serielle schnittstelle vom PC schicke. wenn 
ich nun die selben Daten über den 2ten µC erzeuge und zu dem sende der 
es auf die SD karte schreiben soll, funktioniert es nicht. ich poste mal 
den code. die main.c ist die datei die auf den µC gespielt wird, welcher 
die daten zu dem 2ten sendet.
main_simple.c ist deine datei nur wenig verändert

hoffe du kannst mir helfen

von Daniel R. (zerrome)


Lesenswert?

Hallo zusammen.


@ Juergen (Gast)

Ja stimmt, ich bin davon ausgegangen, dass man nur am Anfang die freien 
Sektoren bestimmt...
Das wird geändert. Dein Vorschlag funktioniert so.


@ Alex Glaser (almalex)

Um mir das genauer anzuschauen fehlt mir momentan einfach die Zeit. 
Vielleicht so in 1,5-2 Wochen, sorry.

Es gibt auch noch einen kleinen Bug, der nur auftritt wenn man die Lib 
im Read-Only Modus betreibt. Dann hat nämlich ffopen evtl. nicht immer 
einen Rückgabewert... Ist aber eigentlich kein Funktionaler Fehler.

Grüße Daniel

von Andre (Gast)


Lesenswert?

Hay Leute

Ich habe nun auch mal versucht unter Codevision zum Laufen zu bekommmen.

Aber leider ohne erfolg.

Ich habe mir die CodeVision_SDLIB_v0.4.4.zip runter geladen und an den 
Mega128 Angepasst. Ich nutze zwar den Mega1281 Aber der ist gleich den 
128 nur mit mehr S-Ram.

Habe das ganze System unter 3,3V laufen den AVR sowie auch 
Verständlicherweisse die SD-Karte.

Kann mir jemand mal einen code in Codevision Posten der Funktioniert.?

Die mmc_init() bzw. die INIT sieht so aus

  if(mmc_init() !=0)
  {
    LED_Rot^=1;
    while(1);
  }
    LED_Gruen^=1;

Aber es bleibt immer auf Rot nie auf Grün und sagt keine SD Karte 
Eingesteckt.

Kann mir jemand weiter helfen.?


Vielen Dank schon mal

von Daniel R. (zerrome)


Lesenswert?

Hallo,
erstmal solltest du besser die neuste Version auf Codevision portierten.

Dann ist das so nicht richtig wie du das machst. So wird nur ein mal 
versucht die mmc/sd karte zu initialisieren...

Das wäre richtig:
1
while (0!=mmc_init()){
2
    LED_Rot^=1;
3
  }
4
LED_Gruen^=1;

jetzt wird rot bei jedem versuch getoggelt und grün nach erfolgreichem 
initialisieren...

Grüße Daniel

von Andre (Gast)


Lesenswert?

jup das war es nun geht die init Funktion. Danke  @Daniel R.

Ich nutze die CodeVision_SDLIB_v0.4.4

nun habe ich auch die filefat.c Eingebunden.

habe auch alle fehler soweit Korrigiert und angepasst.

Nur meckert er  mich bei dieser geschichte voll

Error: filefat.c(635), included from: Neu.c: expression must be a 
pointer to a complete object type

in der Zeile steht das hier

*(unsigned char*)firstCluster++=sector[row+26];

und das macht er durch weg. :-(


MFG: Andre

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ich könnte mir da zwei Möglichkeiten vorstellen, warum das nicht klappt.

1. Versuchs mal so:
1
*(unsigned char*)firstCluster=sector[row+26];
2
firstCluster++;

2. Versuchs mal so:
1
*(unsigned char*)firstCluster++=(unsigned char*)sector[row+26];

Klappt da was von?
Das ist wegen dem CodeVision Compiler, da müsste man mal raus finden 
warum der den void Pointer so an meckert..

Mit nimm die neuste Version zum anpassen meinte ich die Version 0.5.7

Grüße Daniel

von Andre (Gast)


Lesenswert?

So gut soweit habe ich nun versucht erstmal die mmc.c, mmc.h und 
config.h eingebunden.

nun habe ich dort das problem das er mir das hier anmeckert

    loop_until_bit_is_set(SPSR,SPIF);

Error: mmc.c(418), included from: Neu.c: undefined symbol 
'loop_until_bit_is_set'



MFG: Andre

von Andre (Gast)


Lesenswert?

ich meinte ich habe die Version 0.5.7 eingebunden.

von Andre (Gast)


Lesenswert?

Ich glaub ich bleib weiter bei der CodeVision_SDLIB_v0.4.4 den da habe 
ich die wenigsten fehler und so.

Den das nimmt ja hier garkein ende mit den ganzen ram. :-)


MFG: Andre

von Daniel R. (zerrome)


Lesenswert?

Hallo,
1
loop_until_bit_is_set(SPSR,SPIF)

ist ein Makro aus der avr-libc, SPSR ist ein Register und SPIF ist ein 
Bit in dem Register. Das Makro ist sehr schnell, daher benutze ich es. 
Dahinter steckt eigentlich:
1
do { } while ((!((*(volatile uint8_t *)(((uint16_t) &(SPSR)))) & (1 << (SPIF)))))

Ändere mal das Makro so wie hier beschrieben. Dann wirst du 
wahrscheinlich noch nen Haufen anderer Fehler bekommen wegen den 
unterschiedlichen Register Namen, die musst du alle ändern.

Poste doch mal die Fehlermeldungen, vielleicht kann man dann mehr sagen. 
Du kannst ja die Teile die in der CodeVision_SDLIB_v0.4.4 stehen 
vergleichen mit den stellen aus der 0.5.7 die nicht auf Anhieb laufen...
Oder du fragst mal nett bei  "Lolipop Er (lolipoper)" ob er nicht 
nochmal die 0.5.7 auf CodeVision portieren mag. Oder du nimmst den 
avr-gcc anstelle von CodeVision :)

Viele Grüße Daniel

Persönliche Nachricht an "Lolipop Er (lolipoper)" : 
http://www.mikrocontroller.net/user/show/lolipoper

von Bernd (Gast)


Lesenswert?

Hallo,

wie schnell kann man mit dieser Bibliothek auf einer SD-Karte 
schreiben?Wie lange brauche ich z.B. um 10 MB zu schreiben?

Danke im Vorraus und Grüße
Bernd

von Matze (Gast)


Lesenswert?

Das hängt von der Taktrate deines µC zusammen. Außerdem ist deine 
Speicherkarte entscheidend. Also einfach mal ausprobieren ;)

Grüße,
Matze

von Daniel R. (zerrome)


Lesenswert?

Hallo,
der Matze hat es schon erwähnt, es hängt von verschiedenen Faktoren 
ab...

Ich sage mal so, mit einer neueren SD Karte und im Multiblock-write 
Modus, bei 10 MHZ SPI Takt etwa 40 Sekunden für 10 MBytes.

von Thorsten (Gast)


Lesenswert?

Hallo,
ich benutze die Fat32 in einer Portierung auf den XMega. Leider ist in 
der Applikation öfter mit dem Wegbrechen der Versorgungsspannung zu 
rechnen und der Controller schreibt ständig in wachsende Dateien.
Gibt es ausser einer Pufferung der Versorgungsspannung eine Möglichkeit 
ein korruptes Dateisystem zu vermeiden?
Ständige ffclose() Aufrufe gefolgt von erneutem öffnen der Datei sind 
denke ich nicht so gut.

von Daniel R. (zerrome)


Lesenswert?

Hallo,
wenn man jetzt so etwas wie "flush" beim schreiben machen würde, also um 
den Dateieintrag zu updaten und die aktuell gepufferten Daten zu 
schreiben, müsste man genau die Dinge machen, die bei einem ffclose 
auftreten. Das einzige was man evtl. übergehen könnte wäre das suchen 
der Datei im Verzeichnis, beim erneuten öffnen. Das wirkt sich aber nur 
bei vielen Dateien in einem Verzeichnis aus.
Generell mach ich mir aber mal Gedanken ob da nicht was zu machen ist.
Umgehen könnte man dass, wenn man nicht nur 512 Bytes puffern würde, 
sondern 1024 Bytes. Dann wären die Möglichkeiten wesentlich größer, aber 
so muss alles durch den 512 Bytes Puffer.
In FAT32 ist ein Journal nicht vorgesehen, wie es bei allen neueren 
Dateisystemen Standard ist. Da muss man dann über dem Standard selber 
was machen...

Viele Grüße

Daniel

von Steffen (Gast)


Lesenswert?

Hallo,

ich habe gelesen, dass du mit linux arbeitest, hast du dir das Image der 
Karte per dd geholt oder wie hast du das gemacht.

MfG

von Daniel R. (zerrome)


Lesenswert?

Hallo,
nein mit dem Tool WinHex, das läuft auch unter Linux gut.
Generell muss man aber nur alle Sektoren einer Karte in eine Datei 
packen, das reicht dann schon...

Grüße Daniel

von Lowtzow .. (lowtzow)


Lesenswert?

hallo

tolles projekt!
ich habe diese library auf einem mega328 im einsatz. wobei daten die 
ausgewertet wurden auf einem lcd angezeigt werden und auf die sd karte 
geschrieben werden. und noch immer mehr als die hälfte an speicher platz 
;-)


möchte noch zusätzlich gps implementieren, wie könnte man das am 
einfachsten realisieren?
kann ich hierbei die uart so verändern, damit sie nur mit dem gps modul 
kommuniziert oder ist diese systembedingt erforderlich?

und wie kann man den syste der einträger in der txt verändern, zb dass 
durchnummerierungen erfolgen

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ja die UART kann man einfach benutzen, es wird nur SPI von der Lib 
benutzt.

>und wie kann man den syste der
>einträger in der txt verändern, zb dass
>durchnummerierungen erfolgen

Wie meinst du das?

Willst du eine große Datei erstellen in der alle NMEA Einträge stehen?
Dann musst du die Lib im überschreiben Modus benutzen, dann kannst du 
einfach die Datei öffnen und was anhängen...


Grüße Daniel

von Lowtzow .. (lowtzow)


Lesenswert?

super!

hab gesehn, man kann echt viel mit deinen libs anstellen ;-)
wie wirkt es sich aus, wenn der ffwrites(text) oder andere aktivitäten 
der sd von einem interrupt unterbrochen werden?

habe zb einen interrupt laufen der jede ms ausgelöst wird, brauch diese 
zeit um die flanken eines externen interrupts zu messen.
auf die karte sollte im sek takt geschriben werden. habe bemerkt, dass 
nach einiger zeit anscheinend der schreib prozess wesentlich länger 
braucht. macht sich bemerkbar da das lcd in der selben schleife hängt 
und manchmal 5sek und länger nicht aktualisiert wird. liegt das 
vielleicht an interrupts?
nur wenn ich die interrupts deaktiviere für den sd schreib prozess, kann 
ich einige sekunden keine messwerte empfangen.

von Daniel R. (zerrome)


Lesenswert?

Das ist so schwer zu sagen, da ich nicht genau sehen kann wie du die Lib 
in deinem Code benutzt.
Aber wenn du die Anbindung an die Karte mit Hardware SPI machst, sollte 
eine Unterbrechung keine Probleme machen, da SPI per Definition Clock 
hörig ist. Also könnte man zwischen 2 zu Übertragenden Bytes auch Pausen 
einlegen. Ich gehe mal davon aus, dass wenn man ein Byte auf die 
Hardware SPI gibt, dies auch nicht von Interrupts unterbrochen wird, 
weil Hardware...
Schließt und öffnest du die Datei in die du schreibst bei jedem 
Messwert?

Grüße Daniel

von Lowtzow .. (lowtzow)


Lesenswert?

da ich derzeit noch am erproben bin, verwende ich deine lib im großen 
und ganzen original nur leichte anpassung für mega328. aufrufe werden 
nach der mainsimple vorlage gemacht, wobei die datei auch jedesmal 
geschlossen wird

mir ist in der nacht noch etwas eingefallen. da ich noch freien speicher 
habe, könnte ich ca 60sek am mega328 speichern und dann gesammelt 
übetragen mit intterupt disable (2-3fehlende werte in einer min ist 
nicht so schlimm)

kann sein, dass das spulen zum dateiende nach einiger zeit länger 
dauert?!
1
 
2
      sprintf(text,"%u",(int)heartbeat_output);
3
4
// Dateinamen müssen in diesem Format sein !
5
    unsigned char file_name[20]="TEST    TXT";
6
7
    // string zum in die datei schreiben schreiben
8
    //unsigned char str[13]="Hallo Datei!";
9
//    unsigned char str[13]="heartbeat_output";
10
11
12
    // Datei existiert nicht, also anlegen !
13
    if(MMC_FILE_NEW == ffopen(file_name)){
14
15
       // schreibt String
16
       //ffwrites(str);
17
     ffwrites(text);
18
19
       // neue Zeile in der Datei
20
       ffwrite(0x0D);
21
       ffwrite(0x0A);
22
23
       // schließt Datei
24
       ffclose();
25
     }
26
27
28
29
     // Datei existiert, also anhaengen !
30
     else{
31
32
       ffseek(file.length);   // spult bis zum Dateiende vor um anzuhaengen !
33
34
       // schreibt String
35
       //ffwrites(str);
36
     ffwrites(text);
37
38
39
       // neue Zeile in der Datei
40
       ffwrite(0x0D);
41
       ffwrite(0x0A);
42
43
       // schließt Datei
44
       ffclose();
45
     }
46
47
48
     // Datei existiert, also kann man lesen.
49
     if(MMC_FILE_EXISTS == ffopen(file_name)){
50
51
        // setzen einer Variable und dann runterzaehlen geht am schnellsten !
52
        unsigned long int seek=file.length;
53
54
        // lesen eines chars und Ausgabe des chars.
55
        // solange bis komplette Datei gelesen wurde.
56
        do{
57
           uputc(ffread());
58
        }while(--seek);
59
60
        ffclose();

von Daniel R. (zerrome)


Lesenswert?

Hallo,

>kann sein, dass das spulen zum dateiende
>nach einiger zeit länger dauert?!

Das kommt auf die Datenmenge an, da man sich durch die schon verketteten 
Cluster suchen muss. Ist die Datei um die mehreren MB oder sogar GB kann 
das dauern.

>..und manchmal 5sek und länger..

5 Sekunden ist ne verdammt lange Zeit. Stimmt da vielleicht irgend etwas 
anderes nicht? In 5 Sekunden würde man wenn es gut läuft 1,3 Millionen 
Bytes auf eine Karte schreiben können.
Blockiert der Interrupt sich selber oder so?

Poste doch mal den ganzen Code, als Datei Anhang. So kann ich da nicht 
viel dazu sagen. In dem von dir gezeigten Code sehe ich keinen Fehler...

Grüße Daniel

von Lowtzow .. (lowtzow)


Lesenswert?

Daniel R. schrieb:
> 5 Sekunden ist ne verdammt lange Zeit. Stimmt da vielleicht irgend etwas
> anderes nicht? In 5 Sekunden würde man wenn es gut läuft 1,3 Millionen
> Bytes auf eine Karte schreiben können.
> Blockiert der Interrupt sich selber oder so?
>
> Poste doch mal den ganzen Code, als Datei Anhang. So kann ich da nicht
> viel dazu sagen. In dem von dir gezeigten Code sehe ich keinen Fehler...

hab mich ein bisschen herumgespielt.
habe testweise werte nacheinander auf die karte geschrieben, mit 
systemzeit in ms. dabei ist mir aufgefallen, dass der datenstring sehr 
schnell ca.20ms auf die karte geschrieben wird.
also am schreiben kanns nicht liegen.
testweise, habe ich die datei nicht geschlossen, selbes problem, je 
länger die datei wird desto länger hält sich der mega328 mit der sd 
karte auf.

und dann ist mir eingefallen, dass in deinem beispiel die datei über den 
uart wieder ausgelesen wird. diese funktion ist zwar in meinem code auch 
vorhanden, nur wird sie nicht gebraucht!
und na klar nach 30x25 Zeichen braucht das auslesen über den uart schon 
ne zeit...

also auslesen raus und alles super toll jetzt! danke für den support 
hier und tolle libs für die sd-card hast du geschrieben, die tadelos 
funktioniern!! danke!

der fehler war mein programm...
der fehler war wie immer menschlich ;-)

von Daniel R. (zerrome)


Lesenswert?

Schön das es jetzt klappt :)

Oft muss man Geduld haben wenn etwas nicht klappt und man nicht richtig 
Debuggen kann wegen fehlender Geräte wie z.b. Spektrum-Analyzer oder 
Logik-Analyzer... Da ist Kreativität gefragt ;)

Viele Grüße

Daniel

von Uhu U. (uhu)


Lesenswert?

Weißt du, daß es hier auf dem Forum svn gibt, in das man solche Projekte 
einchecken kann?

Beitrag "Hinweis: Artikelsammlung"

Das macht es deutlich einfacher, die aktuelle Version zu finden ;-)

von Daniel R. (zerrome)


Lesenswert?

Hm, ja hatte mir das mit dem SVN auch schon mal überlegt.
Werde das mal in Angriff nehmen.

Auf http://www.mikrocontroller.net/articles/AVR_FAT32 unter "4. Der 
Code"
ist aber auch immer die neuste Version verlinkt.

Aber stimmt schon SVN wäre schöner.

Viele Grüße

Daniel

von Mark (Gast)


Lesenswert?

Hi,

vielen Dank für die Library. Ich habe dazu eine Frage:
Warum wird ein anderer Pin als der Hardware SPI SS für MMC_Chip_Select 
verwendet? Funktioniert das nicht mit dem SPI SS?
Bei meinen Board ist das CS der SD Karte an dem SPI SS angeschlossen. 
Ich habe das Problem, dass meine 2 GB Sandisk MicroSD Karte nicht 
erkannt wird. Ich habe Karten von zwei verschiedenen Herstellern 
getestet. Bei MMC_Chip_Select habe ich den Pin von SPI SS angegeben. 
SDHC ist auf false. Sonst ist es der gleiche Code wie im Wiki Eintrag.


Vielen Dank & Gruß
Mark

von Daniel R. (zerrome)


Lesenswert?

Hallo,
das mit dem MMC_Chip_Select Pin hatte ich einfach so von Ulrich Radig 
übernommen, ohne viel darüber nachzudenken. Warum genau es nicht klappt, 
wenn man den richtigen SPI SS Pin nimmt weiß ich nicht genau. Müsste man 
mal im Datenblatt nachschauen, vielleicht muss man da nur noch was 
einstellen, damit es klappt.
Kannst du nicht einfach einen anderen Pin nehmen?

Grüße Daniel

von Werner B. (werner-b)


Lesenswert?

Das ist mir schön öfter aufgefallen. Manche Leute haben regelrecht Angst 
vor dem SS Pin. Könnte das evtl. mit dem (berechtigterweise) miserablen 
Image des Namens zu tun haben?
 :-\

von Mark (Gast)


Lesenswert?

Zur Info: Es funktioniert auch mit dem SPI SS, ein Kontakt des MicroSD 
Slots war nicht richtig angelötet.

von Amega (Gast)


Lesenswert?

Hallo,

Neue Dateien werden nich angelegt, append funktioniert wenn die Datei 
nicht leer ist. Habt ihr ne Idee?

SanDisk MicroSD 2GB(+Adapter), 3.3V LM317, Pagelwandler - 3.3K,1.8K
ATMega32, 16MHz
stable-mmc-0.5.7



Mfg,
Amega

von Daniel R. (zerrome)


Lesenswert?

Hallo,
zeig mal den Code, hast du in der config.h etwas geändert?

Besorg dir für 20 Cent nen HC4050 als Pegelwandler oder lass den Atmega 
mit 3,3 Volt laufen.

Du könntest auch mal probieren ob die Einstellung in der config.h,
1
#define MMC_MAX_SPEED FALSE

etwas bringt.

Viele Grüße

Daniel

von Daniel R. (zerrome)


Lesenswert?

So, es gibt jetzt ein SVN-Repository für die Bibliothek.
Dort wird immer die Neuste Version zu haben sein.
Immer als AvrStudio Projekt und mit Linux Makefile.

Das jetzige Update enthält eigentlich nur 2 Fixes.
1. Ein return wert ist dazu gekommen in der Funktion ffopen
2. In der fat_getFreeBytes wird der Sektor anders geladen.

Zusätzlich sind noch ein paar Funktionen static geworden.

Viele Grüße

Daniel

Link zu allen SVN:
http://www.mikrocontroller.net/svn/list

Link zur Bib.:
http://www.mikrocontroller.net/svnbrowser/avr-fat32

von Amega (Gast)


Lesenswert?

Hi,
ffopen->fat_loadFileDataFromDir kommt nicht zurück - endloss Schleife?
Hab die SD-Karte under Linux formatiert (fat16,fat32):
fdisk (type 6,b,c), dann mkfs.vfat .
Wie ich schon gerschrieben habe, funktioniert nur wenn die Datei da ist
und nicht leer.

Ich kann versuchen auch unter Windows die Karte zu formatieren.

Mfg

von Amega (Gast)


Lesenswert?

Nachdem ich unter Windows die Karte formatiert habe, wird nun neue Datei 
angelegt, die bleibt aber leer.
Wenn ich noch mal versuche, dann gibts die Datei doppelt.

Wie funktioniert bei auch? Habt ihr mit 2GB Karte getestet?

Bin aber trotzdem froh, dass sich was bewegt :)

von Amega (Gast)


Lesenswert?

Hab bemerkt, dass ich eventuel mkfs.vfat falsch aufgerufen habe.
-F habe ich vergessen
mkfs.vfat -F 32 dev....

von Daniel R. (zerrome)


Lesenswert?

Hallo,
klappt es denn jetzt?

Mit Linux hab ich es nie hin bekommen, dass bei einer frisch 
formatierten Karte das Root Directory mit 0x0fffffff abgeschlossen wird. 
Linux hat da, immer 0x08ffffff oder so draus gemacht. Wenn das Dir dann 
nicht mehr leer ist, ist korrekter Weise 0xffffffff draus geworden.

Kannst du dir die Sektoren der Karte anschauen? Wenn ja sieh mal nach 
wie der Root-Dir Cluster in der Fat aussieht. Hilfreiches Tool dafür 
WinHex. Läuft auch unter Linux.

Viele Grüße

Daniel

von GG (Gast)


Lesenswert?

Servus,

Amega schrieb:

>Wie funktioniert bei auch? Habt ihr mit 2GB Karte getestet?

Ich verwende 3 unterschiedliche Karten, zb. Verbatin Micro 2 Giga

Die Karten funktionieren einwandfrei.

Betreibe meine Karte mit einem Atxmega128a3 mit 16Mhz. SPI-Takt 8Mhz.

fat_getFreeBytes() benötigt bei einer 2 Giga Karte gerademal 200 mS.

Bin voll zufrieden.


Gruß GG

von Amega (Gast)


Lesenswert?

@Daniel:
Addresse 0x200 hat fff8 ffff:

dd if=/dev/mmcblk0p1 of=sdcard.bin bs=512 count=2
hexdump sdcard.bin

0000000 3ceb 6d90 646b 736f 7366 0000 4002 0001
0000010 0002 0002 f800 00ec 0010 0004 0000 0000
0000020 eff0 003a 0000 8929 cb0e 204b 2020 2020
0000030 2020 2020 2020 4146 3154 2036 2020 1f0e
0000040 5bbe ac7c c022 0b74 b456 bb0e 0007 10cd
0000050 eb5e 32f0 cde4 cd16 eb19 54fe 6968 2073
0000060 7369 6e20 746f 6120 6220 6f6f 6174 6c62
0000070 2065 6964 6b73 202e 5020 656c 7361 2065
0000080 6e69 6573 7472 6120 6220 6f6f 6174 6c62
0000090 2065 6c66 706f 7970 6120 646e 0a0d 7270
00000a0 7365 2073 6e61 2079 656b 2079 6f74 7420
00000b0 7972 6120 6167 6e69 2e20 2e2e 0d20 000a
00000c0 0000 0000 0000 0000 0000 0000 0000 0000
*
00001f0 0000 0000 0000 0000 0000 0000 0000 aa55
0000200 fff8 ffff 0000 0000 0000 0000 0000 0000
0000210 0000 0000 0000 0000 0000 0000 0000 0000
*
0000400


Formatiert ahbe ich so:
mkfs.vfat -F 16 /dev/mmcblk0p1

fdisk -l:
        Device Boot      Start         End      Blocks   Id  System
/dev/mmcblk0p1               1       60352     1931256    6  FAT16

von Amega (Gast)


Lesenswert?

Es funktioniert nun!!
1. mkfs.vfat  mit -F 16
2. alles gelöscht und neu kompiliert (make depends funkionieren!?!?)

Ich probiere mal mit Fat32.

von Daniel R. (zerrome)


Lesenswert?

Hallo,
mkfs.vfat formatiert das komisch... hast du keinen Windows Rechner zum 
Formatieren zur Hand?
Es liegt an dem blöden Eintrag für das Root-Dir.

Grüße Daniel

von Amega (Gast)


Lesenswert?

Mit Fat32 ist die endloss Schleife zu beobachten:

        Device Boot      Start         End      Blocks   Id  System
/dev/mmcblk0p1               1       60352     1931256    b  W95 FAT32

hexdump /dev/mmcblk0p1 (sehe ich nirgendwo ffff ffff)
0000000 58eb 6d90 646b 736f 7366 0000 0802 0020
0000010 0002 0000 f800 0000 0010 0004 0000 0000
0000020 eff0 003a 0eb5 0000 0000 0000 0002 0000
0000030 0001 0006 0000 0000 0000 0000 0000 0000
0000040 0000 b429 cb13 204b 2020 2020 2020 2020
0000050 2020 4146 3354 2032 2020 1f0e 77be ac7c
0000060 c022 0b74 b456 bb0e 0007 10cd eb5e 32f0
0000070 cde4 cd16 eb19 54fe 6968 2073 7369 6e20
0000080 746f 6120 6220 6f6f 6174 6c62 2065 6964
0000090 6b73 202e 5020 656c 7361 2065 6e69 6573
00000a0 7472 6120 6220 6f6f 6174 6c62 2065 6c66
00000b0 706f 7970 6120 646e 0a0d 7270 7365 2073
00000c0 6e61 2079 656b 2079 6f74 7420 7972 6120
00000d0 6167 6e69 2e20 2e2e 0d20 000a 0000 0000
00000e0 0000 0000 0000 0000 0000 0000 0000 0000
*
00001f0 0000 0000 0000 0000 0000 0000 0000 aa55
0000200 5252 4161 0000 0000 0000 0000 0000 0000
0000210 0000 0000 0000 0000 0000 0000 0000 0000
*
00003e0 0000 0000 7272 6141 5a4b 0007 0002 0000
00003f0 0000 0000 0000 0000 0000 0000 0000 aa55
0000400 0000 0000 0000 0000 0000 0000 0000 0000
*
0000c00 58eb 6d90 646b 736f 7366 0000 0802 0020
0000c10 0002 0000 f800 0000 0010 0004 0000 0000
0000c20 eff0 003a 0eb5 0000 0000 0000 0002 0000
0000c30 0001 0006 0000 0000 0000 0000 0000 0000
0000c40 0000 b429 cb13 204b 2020 2020 2020 2020
0000c50 2020 4146 3354 2032 2020 1f0e 77be ac7c
0000c60 c022 0b74 b456 bb0e 0007 10cd eb5e 32f0
0000c70 cde4 cd16 eb19 54fe 6968 2073 7369 6e20
0000c80 746f 6120 6220 6f6f 6174 6c62 2065 6964
0000c90 6b73 202e 5020 656c 7361 2065 6e69 6573
0000ca0 7472 6120 6220 6f6f 6174 6c62 2065 6c66
0000cb0 706f 7970 6120 646e 0a0d 7270 7365 2073
0000cc0 6e61 2079 656b 2079 6f74 7420 7972 6120
0000cd0 6167 6e69 2e20 2e2e 0d20 000a 0000 0000
0000ce0 0000 0000 0000 0000 0000 0000 0000 0000
*
0000df0 0000 0000 0000 0000 0000 0000 0000 aa55
0000e00 0000 0000 0000 0000 0000 0000 0000 0000
*
0001400

von Amega (Gast)


Lesenswert?

ich probiere noch einmal unter Winx ... shutdown

von Amega (Gast)


Lesenswert?

Hi Daniel,

Mit Winx Enchantix formatierte (FAT32) Karte funktioniert!

Mfg
Amega

von Amega (Gast)


Lesenswert?

@Daniel: hab diff gemacht und so was gefunden:

21c36
< 00003e0 0000 0000 7272 6141 5a4b 0007 0002 0000  <- Linux
---
> 00003e0 0000 0000 7272 6141 ffff ffff 0002 0000  <-Windows

Weiss ich nicht ob es relevant ist, aber pasten ist kostenlos ;)

Und ab Adresse 0:
< 0000000 58eb 6d90 646b 736f 7366 0000 0802 0020
< 0000010 0002 0000 f800 0000 0010 0004 0000 0000
---
> 0000000 58eb 4d90 4453 534f 2e35 0030 0802 0026
> 0000010 0002 0000 f800 0000 003f 00ff 0010 0000

Mfg

von Amega (Gast)


Lesenswert?

Wäre dann nicht richtig Wert zwischen 0x#FFFFFF8 – 0x#FFFFFFF zu 
erwarten als EOC?

http://www.embedded-code.com/download/mmc_sd_memory_card_driver_technical_manual.pdf
....
0x#FFFFFF8 – 0x#FFFFFFF EOC (End Of Clusterchain) (typically you should 
use 0x#FFFFFFF

von Amega (Gast)


Lesenswert?

Hab die Funktion fat_loadFileDataFromDir geändert und nun filegt das 
Ding :)

fat.c@172
  while(!((  (i>=0x8ffffff && i<=0xfffffff ) 
&&fat.fatType==32)||(i==0xffff&&fat.fatType==16))){// prueft ob weitere 
sektoren zum lesen da sind (fat32||fat16)



Bin neugierig, ob linux-formatierte Karte unter Winx lesbar ist.

von Amega (Gast)


Lesenswert?

Und noch was habe ich festgestellt: append funktioniert bei mir nicht 
wenn die Datei leer ist.

von Amega (Gast)


Lesenswert?

ups 0x#FFFFFF8 != 0x8ffffff !?!?
..war sonnig heute ;)

von Amega (Gast)


Lesenswert?

Und noch was:
http://www.pjrc.com/tech/8051/ide/fat32.html
Also, the end-of-file number is actually anything equal to or greater 
than 0xFFFFFFF8, but in practive 0xFFFFFFFF is always written.

von Daniel R. (zerrome)


Lesenswert?

>ups 0x#FFFFFF8 != 0x8ffffff !?!?
Kommt auf die Endianness an ;)


>fat.c@172
>  while(!((  (i>=0x8ffffff && i<=0xfffffff )
>&&fat.fatType==32)||(i==0xffff&&fat.fatType==16))){// prueft ob weitere
>sektoren zum lesen da sind (fat32||fat16)

Ja sollte so laufen, bläht das den Code auf? Keine Ahnung wie viel mehr 
Aufwand ein größer gleich im Gegensatz zu gleich ist...

>append funktioniert bei mir nicht
>wenn die Datei leer ist.

Das schau ich mir mal an. Aber eigentlich sollte das kein Problem sein, 
weil ans Ende spulen bei Dateigröße 0 kein Problem ist.

file.c@168
while( offset>=512 ){ ...

offset ist hier die Byte Stelle zu der man spulen möchte. Bei Dateigröße 
0 ist das 0 und 0 ist nicht >= 512, also wird in ffseek nichts 
sinnvolles gemacht...

Nur um sicher zu gehen, du appendest ;) ja so oder?
1
if(MMC_FILE_EXISTS == ffopen(file_name)){
2
   ffseek(file.length);
3
   uputc('a');
4
   ffclose();
5
}

Grüße Daniel

von Amega (Gast)


Lesenswert?

End-of-Cluster - FAT32 - >= 0x0FFFFFF8
Der Beweis ist here zu finden:
http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/fatgen103.doc
......
IsEOF = FALSE;
If(FATType == FAT12) {
    If(FATContent >= 0x0FF8)
        IsEOF = TRUE;
} else if(FATType == FAT16) {
    If(FATContent >= 0xFFF8)
        IsEOF = TRUE;
} else if (FATType == FAT32) {
    If(FATContent >= 0x0FFFFFF8)
        IsEOF = TRUE;
}

von Daniel R. (zerrome)


Lesenswert?

Ja krass, das hatte ich doch tatsächlich immer überlesen.
Wird geändert werden, danke.
Gewundert hatte es mich doch schon warum Linux das so seltsam formatiert 
:)

Grüße Daniel

von Alex G. (almalex)


Lesenswert?

kann es sein das man bestimmte ascii zeichen nicht schreiben kann? weil 
ich schicke den richtigen string, und wenn ich die zeichen einzeln 
ausgebe stimmen sie auch, nur auf der sd karte stehen sie nicht
danke mfg alex

von Daniel R. (zerrome)


Lesenswert?

Wenn du Strings mit der Funktion ffwrites schreibst, darf in dem String 
logischerweise kein '\0' alias 0x00 vorkommen, da dies ja ein String 
Ende markiert. Bei anderen Steuerzeichen bin ich mir nicht sicher ob die 
gehen.

Mit ffwrite kannst du jedes Byte Zeichen auf die Karte schreiben.

Falls das immer noch nicht geht, müsstest du mal ein bisschen Code 
zeigen und die Zeichen die du schreiben möchtest.

Viele Grüße

Daniel

von Tom (Gast)


Lesenswert?

Hi,

ich hab ne allgemeine Frage: Warum verwendest du für Strings unsigned 
char* anstatt char*? Die Ascii Tabelle geht doch nur bis 127 und dadurch 
gibt es bei mir viele Warnings.

von Uhu U. (uhu)


Lesenswert?

Da kann ich nur aus dem eigenen Nähkästchen plaudern: signed char ist 
einfach nur krank, wenn es Zeichen und keine int-Werte enthält.

Aber vielleicht ist es auch Gewohnheitssache, mit den Abstrusitäten von 
signed char - Vergleichen zurecht zu kommen.

von Lowtzow .. (lowtzow)


Lesenswert?

habe heute versucht daten über den uart einzulesen, lib ist ja 
vorhanden.

verwende ich jedoch
1
 ugetc();
zum auslesen, dann bekomme ich beim kompilieren folgenden fehler

:369: undefined reference to `ugetc'
1
#include "uart.h"
 ist im maincode geaddet und initalisieren und
1
 uputc(ffread());
 funktioniert im main programm auch, beim kompilieren dabei gibts auch 
keine fehler. nur wenn ich ugetc aufrufen möcte schreit er eine 
fehlermeldung.
kann das bitte mal wer testetn obs ähnliche fehler gibt?!

mfg
low

von Lowtzow .. (lowtzow)


Lesenswert?

hab die einstellung gefunden die geändert werden muss config.h ;-)

von Uhu U. (uhu)


Lesenswert?


von Daniel R. (zerrome)


Lesenswert?

Hm,
hab ich da was überlesen oder geht es im Prinzip nur um vfat, also mit 
langen Dateinamen?

Das die da so auf dem fat noch herumreiten, wird wohl eher irgendwie 
exFat mit Zusammenhängen ?!?

Fat16/32 ist ja schon ziemlich in die Jahre gekommen. Wenn man mal so 
moderne Dateisysteme sieht...

von Lowtzow .. (lowtzow)


Lesenswert?

hallo

wenn ich einen string mit vielen zeichen schreiben will hängt sich das 
programm auf. hab schon vieles probiert. \0 macht auch keinen 
unterschied. anscheinend gibt es ein limit für die stringlänge?! denn 
mit strings die kürzer sind funktioniert alles problemlos. anbei ein 
beispiel für eine länge die bei mir nicht mehr klappt.
1
char map_start[] = "awedawereeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeawedawereeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeawedawereeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\0 ";
2
ffwrites(map_start);

hat wer einen tipp?!

ps. fat32 formatierte karten klappen derzeit auch nicht, kann man das wo 
umstellen?!

speicher ist eigentlich noch da
Program:   14360 bytes (43.8% Full)
(.text + .data + .bootloader)

Data:       1528 bytes (74.6% Full)
(.data + .bss + .noinit)

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ich vermute mal Ram Überlauf. Wo in deinem Programm kommst du auf die 
1528 bytes Ramverbrauch??

Pack den String mal ins Flash und probier das nochmal.
Oder mach ein kleines Array und schreib das wiederholt auf die Karte...

Mit was Fat32 Formatiert? Mit Windows?
Welche Version der Lib nutzt du?
Was genau meinst du mit klappt nicht ?!?

Wenn du ein CharArray so erstellst brauchst du das '\0' am Ende nicht! 
Das wird dann automatisch mit dran gemacht.
1
char map_start[] = "awedaweree";


Welchen Controller benutzt du?

Grüße Daniel

von Daniel R. (zerrome)


Lesenswert?

Hallo,
und wie sieht es aus? Läufts?

von Lowtzow .. (lowtzow)


Lesenswert?

Daniel R. schrieb:
> Hallo,
> ich vermute mal Ram Überlauf. Wo in deinem Programm kommst du auf die
> 1528 bytes Ramverbrauch??
>
> Pack den String mal ins Flash und probier das nochmal.
> Oder mach ein kleines Array und schreib das wiederholt auf die Karte...
>
> Mit was Fat32 Formatiert? Mit Windows?
> Welche Version der Lib nutzt du?
> Was genau meinst du mit klappt nicht ?!?
>
> Wenn du ein CharArray so erstellst brauchst du das '\0' am Ende nicht!
> Das wird dann automatisch mit dran gemacht.
>
>
1
> char map_start[] = "awedaweree";
2
>
>
>
> Welchen Controller benutzt du?
>
> Grüße Daniel

ok, mal wieder ein programmfehler meinerseits ;-)
anscheinend is das ram übergelaufen. habe mal die ganzen strings ins 
eeprom des avr (atmega328p) abegelegt und jetzt klappts das beschreiben 
mit langen strings auf die sd problemlos.
mein ram ist so voll weil ich große array habe ca. 100 uint16_t array 
und dann noch lcd/sd/gps. und alles sehr unaufgeäumt.
das mit fat32 muss ich noch testen, aber ich tipp mal drauf es 
funkt.formatiert ist jedenfalls alles it windows.
bin derzeit ganz zufieden mit fat16 läuft alles super und prima!!  danke 
daniel!!
hab das programm jetzt soweit geschireben, dass ich auf der sd-karte ein 
kml file für google earth  erstelle und die gps koordinaten reinschreib.

mfg low

von Daniel R. (zerrome)


Lesenswert?

Hallo,
es gibt auf http://www.mikrocontroller.net/svnbrowser/avr-fat32/ eine 
neue Version, in der ist nur die Bestimmung des Cluster Endes geändert.
Das behebt das Problem mit Linux formatierten Karten :)

Wurde hier thematisiert 
Beitrag "Re: MMC SD library FAT16 FAT32 read write"

Danke  Amega (Gast)


Grüße Daniel

von aga (Gast)


Lesenswert?

Hallo

ich würde gerne meine gps Datensammlung gerne speichern
und bin auf diesen Foren Beitrag gestoßen

Das was hier angeboten wird ist ein bischen viel
kann mir jemand sagen welche DAteien und Methoden ich brauche, um nur 
die Datensammlung zu speichern.

benutze einen atmega16

mfg aga

von Daniel R. (zerrome)


Lesenswert?

Hallo,
orientier dich einfach an dem Beispiel in der main.c

Oder hier dran: 
http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code_Beispiel

Da ist ein einfaches Beispiel wie man die schreib/lese Funktionen 
benutzt.
Wenn du speziellere Hilfe möchtest, musst du schon ein bisschen mehr 
verraten :)

Oder noch besser ein wenig Code Posten, zu dem man Hilfestellung geben 
kann.

Grüße Daniel

von Nig G. (nig)


Lesenswert?

Hallo Daniel,
erstmal meinen herzlichsten Dank für deine Arbeit an diesem Projekt, das 
über die Zeit wirklich hervorragend geworden ist!

@alle: Mein Dank gilt natürlich auch für alle anderen, die sich an 
diesem Projekt beteiligt haben oder wertvolle Vorarbeit geleistet haben!

Ich verwende die SD-Library (leicht angepasst) auf einem ATmega64 unter 
IAR und soweit läuft auch alles perfekt mit unterschiedlichsten 
SD-Karten.
Nun sind mir aber 3 Dinge/fehler aufgefallen, die ich hier mal 
ansprechen wollte, weil ich die in den bisherigen Diskussionen noch 
nicht finden konnte.

1.) Fehler in der Funktion "fat_loadFileDataFromCluster"?
Beim Vergleich des Dateinamens werden in der folgenden Zeile nur 10 
Zeichen verglichen, obwohl der Dateiname aus 11 Zeichen besteht. 
Folglich wird also das letzte Zeichen ignoriert, wodurch "MEINFILE1.TXT" 
und "MEINFILE1.TX2" im Vergleich identisch sind!
Bisher:
1
if(0==strncmp((char*)file.name,(char*)name,10)){
Korrigiert:
1
if(0==strncmp((char*)file.name,(char*)name,11)){

2.) Fehler in der Funktion "fat_loadSector"?
Am Ende der Funktion steht "return FALSE;" wobei diese Stelle niemals 
erreicht werden kann. Diese Funktion kann in der bestehenden Form nur 
"TRUE" zurückgeben, weshalb sich eine Prüfung auf Fehler bisher auch 
völlig erübrigt. Bei welcher Bedingung, hätte denn FALSE zurückgegeben 
werden sollen?

3.) Hier (http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten) 
steht:
"Nachdem die Karte deselektiert wurde (/CS auf high), die Taktleitung 
noch einige Male pulsen, damit die Karte DO hochohmig/tri-state schaltet 
(vgl. Chans Erläuterungen)."
Das wird in der SD-Library bisher noch nicht gemacht, weshalb ich das 
bei mir noch eingefügt habe. Das könnte z.B. folgendermaßen gelöst 
werden. An jeder Stelle, wo im Source "MMC_Disable()" steht, müsste nur 
ein Schreibbefehl folgen, oder?. So z.B.:
1
MMC_Disable();  // CS High
2
mmc_write_byte(0xFF); // dummy write, 8 CLK-Pulse nachdem CS High, damit die Karte DO tri-state schaltet

Viele Grüße
Nig

von test (Gast)


Lesenswert?

Hallo,

kann mir jemand sagen welche MMC SD Katen man am besten benutzen

die auch günstig zu bekommen sind?!?!


MfG

von Daniel R. (zerrome)


Lesenswert?

Hallo.

@ Nig G. (nig)

Bei Punkt 1 und 2 hast du recht, ist mir irgendwie durchgegangen :)
Wird geändert.

Zu Punkt 3, diese Karten sind SPI hörig, also brauchen eigentlich für 
alles einen CLK um was zu machen, zumindest die meisten. Das mit dem "DO 
hochohmig/tri-state" wirkt sich aber auch nur aus, wenn man mehrere 
"Geräte" am selben SPI Bus hat, sonst wäre das egal.
Wird aber geändert.

Danke für die Unterstützung.

@ test (Gast)

Man kann jede Karte nehmen, auch so ganz billige für 2-3 Euro. Wichtig 
nur, es müssen MMC, SD oder SDHC Karten sein.

Viele Grüße

Daniel

von Daniel R. (zerrome)


Lesenswert?

Ach ja, ich überlege grade die Prüfung in fat_loadSector ganz raus zu 
nehmen, ist zwar nicht so schön ohne Fehler Prüfung, aber so wie es bis 
jetzt immer war bringt es ja auch nix...

Mal als Zwischenlösung:
1
unsigned char fat_loadSector(unsigned long int sec){
2
  
3
  if(sec!=fat.currentSectorNr){
4
  #if (MMC_WRITE==TRUE)
5
    if(fat.bufferDirty==1){      
6
             fat.bufferDirty=0;
7
             if(FALSE==mmc_write_sector(fat.currentSectorNr,fat.sector)) return FALSE; 
8
    }
9
  #endif
10
  if(FALSE==mmc_read_sector(sec,fat.sector)) return FALSE; 
11
  fat.currentSectorNr=sec;      
12
  }  
13
    
14
  return TRUE;             
15
}

von mega8 (Gast)


Lesenswert?

ich bekomme immer die Fehlermeldung aus der funktion ffclose:

../file-0.3.c:119: error: 'kb_buffer' undeclared (first use in this 
function)

Damit liegt der Compiler auch völlig richtig, kb_buffer wurde da 
nirgendwo deklariert, aber hab natürlich nichts verändert, einfach nur 
eure Codebeispiele kopiert.
Muss ich was im Projekt bei AVR Studio einstellen?
Makefile benutze ich nämlich keine...

von Daniel R. (zerrome)


Lesenswert?

Hallo,
oha du versuchst da die Version 0.3 zu kompilieren...
Nimm die aus dem SVN und dann sollte das ohne Probleme gehen.

Viele Grüße

Daniel

PS: In der SVN Version ist auch eine AVR-Studio Projektdatei dabei...

Aktuelle Version: 0.5.9
http://www.mikrocontroller.net/svnbrowser/avr-fat32

von Marek N. (Gast)


Lesenswert?

Moin,

ich experimentiere derzeit auch mit SD-Karten an einem ATmega32. Derzeit 
noch mit dem Code von Ulrich Radig.
Würde gerne mal am WE diesen Code ausprobieren.
Gibt es schon Unterstützung für LFN?

Beste Grüße, Marek

von Daniel R. (zerrome)


Lesenswert?

Hi,
nein gibt es noch nicht.
Hab da aber eine Idee, wie man da tatsächlich reguläre Unterstützung für 
lange Dateinamen hin bekommt ohne nochmal 256 Byte Ram zu brauchen :)
Aber vor Mitte Juli wird da nix draus werden...

Aber es ist jeder herzlich eingeladen mit zu entwickeln. Ich pflege das 
dann in die Lib ein.

Viele Grüße

Daniel

von Thorsten J. (Gast)


Lesenswert?

Hallo,

ich hab nun auch endlich die Software erfolgreich zum Laufen bekommen. 
Der Kasus Knaxus war bei mir, dass ich die Software-SPI verwendet habe, 
welche eben so schnell läuft, wie es der Prozessortakt hergibt. Bei 
18,432MHz ist das für die SD-Karte einfach zu schnell. Ich habe ein paar 
zusätzliche Delays eingebaut und dann ging es.

Von meiner Seite dann auch nochmals vielen Dank, für die ganze Mühe, die 
du bisher hier rein gesteckt hast.

Gruß Thorsten

von Daniel R. (zerrome)


Lesenswert?

Hallo,
kannst du mal zeigen an welchen Stellen du da delays reingebaut hast, 
weil eigentlich ist selbst 20 MHz SPI nicht zu schnell für SD/MMC 
Karten...

Viele Grüße

Daniel

von GG (Gast)


Lesenswert?

Servus,



Thorsten J. schrieb:



> ich hab nun auch endlich die Software erfolgreich zum Laufen bekommen.
>
> Der Kasus Knaxus war bei mir, dass ich die Software-SPI verwendet habe,
>
> welche eben so schnell läuft, wie es der Prozessortakt hergibt. Bei
>
> 18,432MHz ist das für die SD-Karte einfach zu schnell. Ich habe ein paar
>
> zusätzliche Delays eingebaut und dann ging es.

ich betreibe meine SD-Card (Verbatim Micro 2 GB) hardwaremäßig mit 20 
MHZ!
Proz. Atxmega
Prozessortakt 2*10 MHz,keine SPI-Teilung, also 20 MHZ am SPI. Das ist 
eine nachweisbare Geschwindigkeit.


Deine Aussage: „Ein paar zusätzliche Delays“  kann heißen: 1,2 oder xx 
Mhz.

Wei schnell ist der SPI-Takt nun wirklich?

Gruß GG

von Thorsten J. (Gast)


Lesenswert?

Ich hab in der mmc_read_byte() und mmc_write_byte()
1
MMC_Write &=~(1<<SPI_Clock);  //erzeugt ein Clock Impuls (Low)

ergänzt zu
1
_delay_us(SOFT_SPI_DELAY_US);
2
MMC_Write &=~(1<<SPI_Clock);  //erzeugt ein Clock Impuls (Low)
3
_delay_us(SOFT_SPI_DELAY_US);

und hab dann getestet. Die Funktion _delay_us() stammt dabei aus der 
<util/delay.h>.

Für SOFT_SPI_DELAY_US waren Werte größer 0.3 notwendig, damit die Karte 
arbeitet. Das ergibt einen Takt von etwa 300kHz, der jedoch einen hohen 
Jitter aufweist.

Wenn ich das noch recht im Hinterkopf habe war es auch so, dass die 
Karten zur Initialisierung mit maximal 400kHz betrieben werden dürfen. 
Bei Verwendung der Hardware-SPI wird dem auch Rechnung getragen und erst 
nach erfolgter Initialisierung auf volle SPI-Geschwindigkeit geschaltet.

Gruß

Thorsten

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ja guter Einwand. Die Initialisierung im Software SPI Modus schau ich 
mir nochmal an. Bin eh grade eine ordentliche Platine für eine SD Karte 
am machen. Wenn das fertig ist, gibt es eine neue Version...

Danke und viele Grüße

Daniel

von Harry L. (mysth)


Lesenswert?

Hallo,

ich versuch gerade die Funktionen auf einem "myAVR Stamp256 PLUS" zum 
Laufen zu bringen.
http://shop.myavr.de/index.php?sp=article.sp.php&artID=100062

Zunächst mal hab ich in mmc.h folgende Ergänzungen gemacht:
1
  // der SS pin des SPI ports wird nicht benutzt! also da nich die karte anschließen, sondern an MMC_Chip_Select !
2
3
  #if defined (__AVR_ATmega2560__)
4
    #define SPI_MISO            3  //Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist (DO)
5
    #define SPI_MOSI            2  //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist (DI)
6
    #define SPI_Clock           1  //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk)
7
    #define MMC_Chip_Select     0  //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist (CS)
8
    #define SPI_SS              0  //Nicht Benutz muß aber definiert werden
9
  #endif
10
11
  #if defined (__AVR_ATmega128__)


Bei diesem Board ist die CS-Leitung der SD-Karte direkt mit dem SS-Pin 
des Controller verbunden.
Daher hab ich einfach mal ganz "blauäugig" den entsprechenden Portpin in 
die obigen Definitionen eingetragen.

Das mitgelieferte Beispielprogramm liefert "Boot..OK"
Ich hab zur Fehlersuche noch weitere "uputs" eingebaut, und schon der 
nächste Aufruf meldet sich nicht mehr zurück: (keine augabe von uputs)
1
    // Datei existiert nicht, also anlegen !
2
    if(MMC_FILE_NEW == ffopen(file_name)){
3
4
        uputs((uint8_t*)"wrote new File\r\n");

ich würde mich über einen Tip freuen!

Harry

von Harry L. (mysth)


Lesenswert?

Hallo,
das Problem ist gelöst, seitdem ich die aktuelle Version aus dem SVN 
verwende.
Danke nochmal an Daniel für dieses Library!!!

Harry

von Harry L. (mysth)


Angehängte Dateien:

Lesenswert?

Anpassungen für ATMega2560:

Ich hab das Library um Support für ATMega2560 CPUs erweitert.

Im Anhang sind die geänderten Files.

Harry

<edit>

Mein Fehler!
nicht mmc.c, sondern mmc.h wurde angepasst.

von Harry L. (mysth)


Angehängte Dateien:

Lesenswert?

die fehlende mmc.h

Harry

von Daniel R. (zerrome)


Lesenswert?

Hallo,
wird im neuen Release aufgenommen werden.

Danke und viele Grüße

Daniel

von Tim (Gast)


Lesenswert?

Hi,

ich habe mal eine Frage wie ich es schaffe, dass es nur eine FAT auf der 
SD-Karte gibt, ist fürs Verständnis leichter nachzuvollziehen.

von Daniel R. (zerrome)


Lesenswert?

Hi,
unter Linux gibt es die Möglichkeit zu sagen das nur mit 1 er Fat 
formatiert werden soll... Unter Windows geht das so glaube ich nicht.

Viele Grüße

Daniel

von Tim (Gast)


Lesenswert?

Ich habe das bis jetzt immer mit GParted unter ubuntu gemacht, da habe 
ich die Option nur 1 Fat anzulegen noch nicht gefunden. Könntest du mir 
bitte ein Stichwort geben wonach ich besser googlen kann.

von Daniel R. (zerrome)


Lesenswert?

Also so formatiere ich unter Linux Fat32 mit einer Fat und 4 Sektoren 
pro Cluster:
1
/sbin/mkdosfs -v -F32 -f1 -s4 -I /dev/sde

Formatiert wird so das Gerät /dev/sde, das ist bei mir ein Kartenslot 
mit einer SD Karte drin.


Daniel

von Matze N. (hupe123)


Lesenswert?

Hi, ich habe auch mal wieder ein Problem:

Ich will grade die neuste Version einbinden (von 0.5.7 auf 0.5.9).
Ich rufe in meinem Programm an manchen Stellen die ffwrites-Funktion wie 
folgt auf
1
ffwrites("huhu");
jedoch bekomme ich nun zu jedem Schreibbefehl die Nachricht, daß da was 
mit den Definitionen nicht passt. Hier einer der vielen gleichen Fehler:
1
main.c:62: warning: passing argument 1 of 'ffwrites' makes pointer from integer without a cast

Ich habe etwas geforscht und an jeder Ecke steht in der neuen Version 
"unsigned". Und daran wird es wohl auch liegen. Warum wurde das denn 
umgestellt?!

Aber was mir viel wichtiger ist, was kann ich gegen diesen Fehler 
machen?

Vielen Dank für alle guten Ratschläge!! :)

von Daniel R. (zerrome)


Lesenswert?

Hallo,
das hatte mehrere gute Gründe, einer davon ist z.B. das so evtl. das 2er 
Komplement entfällt...
Versuch es so und das Warning verschwindet:
1
ffwrites((unsigned char*)"huhu");

Viele Grüße

Daniel

von Matze N. (hupe123)


Lesenswert?

Cool! Danke! Hätt ich aber auch selber drauf kommen können... :( Naja, 
manchmal is man eben betriebsblind ;)

von Matze N. (hupe123)


Angehängte Dateien:

Lesenswert?

So nun habe ichdas zweite Problem: ich kann weder mit der alten (0.5.7) 
noch mit der neuen (0.5.9) Version auf meine SD-Karten schreiben. Obwohl 
SDHC aktiv ist.
Als Speicherkarten benutze ich die zwei im Foto.
Ich formatiere mit WindowsXP Pro.

Ich habe jeweils mit den Beispiel programmen ausprobiert.
Komisch ist, daß in der neuen Version machmal (jedes 15-20ste Mal) durch 
die
1
mmc_init
 gegangen wird (die drei Punkte erscheinen), jedoch erscheint nie das 
"OK".
Bei der alten Routine klappt noch nicht mal der erste Schritt.

Die Hardware die ich benutze ist ein ATmega128 mit 7,3728Mhz.

Angeschlossen ist alles richtig, sonst würden ja die drei Punkte auch 
nich erscheinen - wurde aber dennoch schon x-Mal kontrolliert.

Kann mir jemand helfen?!

Grüße aus Hannover

von Daniel R. (zerrome)


Lesenswert?

Hallo,
so Fehler wie irgendwas klappt manchmal und manchmal nicht, sind 
meistens Hardware Fehler... Benutzt du Software SPI oder Hardware, wie 
lang sind die Kabel, Welche Spannungs Pegel...
Mach mal ein Bild vom Aufbau, dann kann ich evtl. mehr sagen

Viele Grüße

Daniel

von Matze N. (hupe123)


Lesenswert?

hmm... ich habe eben noch mal alle Lötstellen kontrolliert und 
vorsichtshalber alle nachgelötet - geht aber immer noch nichts.

ich betreibe die karte:
- ohne treiber baustein
- direkt an einem ATmega128
- bei 3,3V.

Meinen Eagleplan habe ich angehängt. Ich hoffe, ich hab keinen Fehler in 
der Verschaltung gemacht :)

Viele Grüße und schon mal besten Dank für deine Hilfe!

von Matze N. (hupe123)


Angehängte Dateien:

Lesenswert?

Hab den Anhang vergessen: hier nun der Schaltplan

von Matze N. (hupe123)


Angehängte Dateien:

Lesenswert?

ich habe eben einfach mal zwei 10k Ohm Pull-Up-Widerstände an die CS- 
und die MISO eingebaut (siehe Anhang), weil ich das hier gelesen hatte: 
http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten. aber das 
hilf auch nichts! Ich verzweifel noch!!! Hilfe!

von Daniel R. (zerrome)


Lesenswert?

Hallo,
du steckst doch den SPI Programmer aus wenn du die Karte testest oder?

Mehr fällt mir grad nicht ein, schaue aber später nochmal genauer...

Viele Grüße

Daniel

von Matze N. (hupe123)


Lesenswert?

Ja, aber klar. Geht aber trotzdem nich...

Viel Spaß beim Fußball nachher!

von Daniel R. (zerrome)


Lesenswert?

Hm, Schaltplan sieht Ok aus.
Jetzt könnte der Fehler immer noch in der Software liegen oder im 
Tatsächlichen Aufbau der Schaltung.
Ich hab selber so eine 2GB Scandisk Karte und mit der funktioniert es...
Hast du was in der config.h geändert oder in der mmc.h ?
Wie sieht die Initialisierung genau aus?
Mach doch mal ein Foto der fertigen Schaltung.

Viele Grüße

Daniel

von Matze N. (hupe123)


Lesenswert?

Hi danke für deine Mühe!!!

Ich denke nich, daß es an der Software liegt. Ich hab nichts in deinem 
Beispielprogramm geändert. Ich will morgen noch mal die Schaltung in 
schön aufbauen - sieht echt nach Kraut und Rüben aus.
Wenns fertig is, lade ich ein paar Fotos hoch.

Grüße und genieß das schöne Wetter - in Hannover sind noch 30°C und ich 
muss raus: hier drinnen sind die nämlich auch ;)

Grüße,
Matze

von Matze N. (hupe123)


Lesenswert?

Hi es lag wirklich nich an der Software. Ich habe zwei Sachen geändert:

1) beim ATmega128 geht der ISP nicht über den SPI sondern tw. über den 
USART0. Ich habe meinen UART-RS232 von dieser doppelbelegten 
Schnittstelle abgelötet.
2) Ich habe gleichzeitig den µC gewechselt. Hatte noch nen zweiten 
mega128.

Ich habe eben nochmal den neuen µC mit eingesteckter RS232 Schnittstelle 
programmiert. Geht trotzdem. Lag also wohl an einem def. µC... Jetzt 
gehts aber!!!
Aber warum mich das jetzt vier Tage meines Lebens kosten musste, weiß 
ich auch nich.. ich hasse diese Kleinigkeiten an denen es immer hängt!

Dennoch vielen Dank für deine Hilfe!

von Daniel R. (zerrome)


Lesenswert?

Hallo,
schön das es jetzt klappt...

Es ist nur Zeitverschwendung wenn man nichts dabei gelernt hat :)

Viele Grüße

Daniel

von Matze N. (hupe123)


Angehängte Dateien:

Lesenswert?

Hi,

ich habe da etwas ganz komisches grad festgestellt. Ich kann in eine 
Datei mit einer Funktion nichts schreiben.

Ich will in eine Datei für eine Log-Datei bevor die Daten aufgezeichnet 
werden eine Startsequenz schreiben (Funktion: sd_geschw_start(void)).
Ich habe in die Datei eine UART-Ausgabe ("start") eingebaut; diese 
erscheint auch auf meinem Terminal, aber es steht kein "huhu" in der 
Datei. Nur ein "ende"... WARUM zu Teufel?!
Hat jemand ne Idee?

Grüße,
Matze

von Daniel R. (zerrome)


Lesenswert?

Hallo,
bei dem Stück Code das du gepostet hast, zähle ich ~95 Bytes nur an 
Ascii Zeichen... Das ist ziemliche Ram Verschwendung...

Bin mir jetzt da grad nicht sicher, aber benutzt du fat_str richtig?
Versuche mal an ffopen einen festen Dateinamen zu übergeben, um das 
Problem einzugrenzen.

Ach ja und schließt du die Datei auch irgendwann vor verlassen des 
Programms auch?!?

Viele Grüße

Daniel

von Matze N. (hupe123)


Lesenswert?

Hi Daniel,

ich habe den Tag über in meinem Wust an Funktion gewütet und vieles 
zusammen gestrichen, dabei fiel mir auf, daß in einer anderen Datei an 
zwei stellen wirklich das "ffclose()" gefehlte... dennoch danke für 
deine Mühe. Jetzt geht alles :D

Morgen gibts dann erste Probeläufe mit meinem neuen Datenlogger :D :D

Gute Nacht,
Matze ;)

von Matze N. (hupe123)


Lesenswert?

So geht alles. Allerdings habe ich grade versucht eine 
Verzeichnisstruktur anzulegen. Beim Aufruf von
1
ffmkdir
 habe ich aber noch Probleme:

Mein Quelltext dazu sieht wie folgt aus:
1
 unsigned char verzeichnis[13]=  "TEST";  
2
ffmkdir(verzeichnis);
(Natürlich nachdem die Karte initiallisiert wurde :)
Auf meiner SD-Karte taucht auch ein Ordner auf. Allerdings kann ich 
diesen nicht Öffnen. Windows XP Pro sagt mir:
1
TEST bezeiht sich auf einen Pfad, der nicht verfügbar ist. Dieser kann auf einer Festplatte dieses Computers [...] sein.Stellen Sie sicher, daß der Datenträger korrekt eingelegt ist, [...]. Und wiederholen sie den Vorgang. ...
Muss ich bei dem Funktionsaufruf irgendwie mehr beachten?!

Achja: wieso funktionieren eigentlich nur Grossbuchstaben sowohl bei 
Dateinamen als auch bei Verzeichnissen?!

Danke für deine Hilfe,
Matze ;)

von Daniel R. (zerrome)


Lesenswert?

Hallo,
versuch mal "TEST       " als Verzeichnisname ( 4 Buchstaben und 7 
Leerzeichen). Das mit den Großbuchstaben ist noch aus der DOS Zeit, also 
aus der Fat16 Zeit quasi.
Wenn ich lange Dateinamen Unterstützung mit eingebaut habe wird sich das 
alles etwas vereinfachen, zumindest in der Anwendung :)

Viele Grüße

Daniel

von Matze N. (hupe123)


Lesenswert?

Viel besser! Jetzt gehts!!!

Danke!

von Andre V. (Firma: -----) (fichte)


Lesenswert?

Sagt mal hat es schon jemand geschaft es unter Codevision zum Laufen zu 
bekommen.?


Habe jetzt schon soviel Probiert aber leider ohne erfolg. :-(

von Daniel R. (zerrome)


Lesenswert?

Hallo,
wenn mir ja jemand sagen könnte wie CodeVision mit void Pointern umgeht 
könnte ich da vielleicht was machen... Aber die Dokumentation da finde 
ich etwas dürftig. Glaube es hakt da am meisten, der Rest sind ein paar 
Register und Kleinigkeiten...

Grüße Daniel

von Andre V. (Firma: -----) (fichte)


Lesenswert?

Habe mir mal vor einigen tagen die Neue Light Version von Codevision 
gezogen und getestet.
Die haben ja eine Sd Lib drin und die Funktioniert ja auch super.

Nur komme ich nicht ganz zurecht damit.
Kam zwar auf Display den Inhalt der Datei schreiben und auch Ordner etc. 
aber ich möchte die Werte für andere Sachen Übernehmen und das geht 
irgentwie nicht.

MFG: Andre

von Rene (Gast)


Lesenswert?

Hallo zusammen,

ich wollte gerne wissen, welche Lesegeschwindigkeiten ich bei der 
Verwendung dieser FS32-Bibliothek von SD-Karten zu erwarten habe.

Im Einsatz soll ein ATmega168 mit 8 Mhz eingesetzt werden.
SPI in Hardware mit halber Taktgeschwindigkeit.

Und gibt es Möglichkeiten die Leserate zu maximieren, z.B. FAT16 anstatt 
FAT32?

MfG
Rene

von Daniel R. (zerrome)


Lesenswert?

Hallo,
also wesentlich schneller wird es durch Fat16 nicht werden, da das nur 
mit den Fat einträgen selbst in Zusammenhang steht. Also nur bei Fat 
lookups ins Gewicht fällt...
Also mit Fat32, multiblock-write und 4 Mhz SPI werden wohl so um die 
100-150 k Bytes/Sec gehen. Mit MMC Karten evtl. sogar mehr.

Viele Grüße

Daniel

von Rene (Gast)


Lesenswert?

Hi Daniel,

danke für die prompte Antwort.

Das mit dem Multiblock ist ja so eine Sache, da es wohl nicht von jeder 
Karte unterstützt wird.
Wie ist denn die maximal zu erwartende Leserate ohne 
Multiblock-Unterstützung?
Ich würde gerne universell bleiben, was die SD-Karten angeht.

MfG
Rene

von Daniel R. (zerrome)


Lesenswert?

Hm,
ich hab nur eine uralte Karte die Multiblock nicht unterstützt.
Bei den neueren sollte das wohl immer gehen.
Die Geschwindigkeit hängt auch stark von der Karte ab.
Schätzungsweise wird lesen auch im Bereich 100-150 kBytes/sec liegen...

Viele Grüße

Daniel

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Hallo,
hier mal eine kleine Beta der Version 0.6
Falls da mal jemand reinschauen mag :)

Neu:
Lange Dateinamen, kleinere Vereinfachungen.

Was geht noch NICHT:
Root dir bei Fat16 beschreiben wenn dort schon mehrere Einträge sind.
Einen vollen Ordner erweitern.

Was geht:
Dateien mit langem Dateinamen lesen.
Ordner mit langem Dateinamen lesen/wechseln zu.

Beim Anlegen wird wie gesagt noch der Ordner nicht erweitert!
Bei einem leeren Ordner und 4 Sektoren/Cluster könnte man aber 
mindestens 4 Dateien mit Dateinamen von 255 Zeichen Länge anlegen ;)

Datei mit langem Dateinamen anlegen löschen.
Ordner mit langem Dateinamen anlegen rekursiv löschen.

Beispiel für den Aufruf:
1
ffopen((unsigned char*)"langer name test.txt")

So wird wie gehabt, die Datei angelegt wenn nicht vorhanden, oder 
geöffnet wenn vorhanden.

Viele Grüße

Daniel

von martin (Gast)


Lesenswert?

hallo
funktioniert auch eine microsd mit einem adapter?

von Daniel R. (zerrome)


Lesenswert?

Hallo,
was meinst du mit einem Adapter?
Ein Card-slot?!?
MicroSd geht.

Viele Grüße

Daniel

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Hallo,
hier mal die zweite Beta.

Lange Dateinamen werden jetzt komplett unterstütz. Bei Ordnern und 
Dateien. Das ist allerdings nicht ganz Standard konform. Sollte aber 
keine Probleme Machen solange man die Karte mit Geräten liest/schreibt, 
die auch lange Dateinamen unterstützen !

Es gibt eine Option in der config.h die heißt "MMC_ENDIANNESS_BIG", wie 
der Name vermuten lässt, kann damit die Byteorder umgestellt werden. Wer 
mit den void Pointer Probleme hatte sollte das mal ausprobieren :)

Die Funktion "fflushFileData()" kann jetzt während geschrieben wird 
aufgerufen werden, sie sorgt dafür, dass die Dateiinformationen 
gesichert werden. Allerdings sollte das möglichst selten gemacht werden, 
da immer mindestens 2 Sektoren geschrieben werden müssen !

Viele Grüße

Daniel

von Daniel R. (zerrome)


Lesenswert?

Soo, ist fertig :)

Wäre schön, wenn ich evtl. ein bisschen Feedback bekommen könnte, falls 
irgendwo was schief läuft oder es Verbesserungen gibt.

Das einzige Problem, dass immer noch besteht ist, dass bei Software-SPI 
bei der Initialisierung nicht langsamer getaktet wird, da is mir noch 
nicht wirklich was schönes zu eingefallen :)

Die neue Version gibts hier: 
http://www.mikrocontroller.net/svnbrowser/avr-fat32

Viele Grüße

Daniel

von Daniel R. (zerrome)


Lesenswert?

Ach ja, Wiki:http://www.mikrocontroller.net/articles/AVR_FAT32
wird noch angepasst werden...

von Buzzwang (Gast)


Lesenswert?

Hallo,
ich bin neu hier und habe es mal ausprobiert.

Die 0.6.0 hat nicht getan !
Ich habe es 1:1 genommen und laufen lassen.
Der Controller konnte wohl schreiben + lesen + zufügen.
Aber in Windows wurde die Datei nicht erkannt. Windows zeigte die Datei 
mit "Test.txt." (mit '.' am Ende) mit 0kb an.
Öffnen und Löschen ging nicht. Nur neu formatieren.

Danach bin ich auf die 0.5.9 umgestiegen. Hat geklappt.

Info:
2GB Flash Karte
ATMEGA16 @ 16 MHz

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ja ich war irriger weise davon ausgegangen, dass wenn Linux das 
ordentlich anzeigt, Windows das auch macht. Macht es aber nicht...
Werde später ein update machen, da gibts dann auch noch mehr neue Sachen 
:)

Viele Grüße

Daniel

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

So neue Version 0.6.1 hochgeladen.

http://www.mikrocontroller.net/svnbrowser/avr-fat32/

Man kann jetzt wesentlich mehr konfigurieren in der config.h


Viele Grüße

Daniel

PS: Als Anhang noch ein Benchmark Programm für atmega168 @ 16 MHZ

von Jens (Gast)


Lesenswert?

Hallo!
Also ich habe getestet 0.6.0 - das Problem mit dem nich lesen können 
etc. unter Windows hatte ich auch. Jetzt habe ich 0.6.1 getestet, im 
Prinzip funktionierts, wenn die Karte leer ist legt es die Datei an, 
allerdings steht dann 2 x "Hallo Datei!" in der Datei, je einmal in 
einer Zeile.
Ist das normal / gewollt?
Darüber hinaus, befindet sich eine leere test.txt auf der Karte passiert 
nichts bzw. das Programm kommt nicht zum Ende - habe 3 LED zum debuggen, 
irgendwo nach dem init bleibts stehen und die Datei bleibt leer, ich 
werde berichten wenn ich den Wunden Punkt gefunden habe ...

Ich verwende einen ATmega2561 @ 16MHz, sandisk 1GB bzw. Platinum 2GB

Aber ne tolle Sache ischs in jedem Fall

Gruß Jens

von Jens (Gast)


Lesenswert?

okay manchmal beantworten sich fragen von selber, das mit dem doppelten 
vorkommen des "Hallo Datei!" ist gewollt, also streichen wir die Frage!

von Daniel R. (zerrome)


Lesenswert?

Hallo,

>Darüber hinaus, befindet sich eine leere
>test.txt auf der Kart

das ist nicht normal soweit ich verstehe was Du machst. Zu welcher Datei 
befindet sich die leere test.txt auf der Karte?

Grüße Daniel


PS: Bin für jede Anregung dankbar !

von Jens (Gast)


Lesenswert?

nein nein, weil 0.6.0 nicht funktioniert hatte hab ich etwas rumprobiert 
- u.a. hatte ich eine leere test.txt angelegt, nach dem Durchlauf des 
Programms war die dann immernoch leer, das war dann aber auch bei 0.6.1 
so.
Werde mich noch n bissi mehr damit beschäftigen, vielleicht kann ich ja 
noch was konstruktives beitragen ;)
Grüßle

von Uwe S. (lan-opfer)


Lesenswert?

...kann mir jmd. ein wenig behilflich sein?? Ich habe Version 0.6.1 
heruntergeladen, im AVR-Studio meinen Controller (XMeaga 64A3) 
eingestellt und compiliert. Es hagelt gleich einige Fehlermeldungen:
../mmc.c:128: error: 'DDRB' undeclared (first use in this function)
../mmc.c:128: error: (Each undeclared identifier is reported only once
../mmc.c:128: error: for each function it appears in.)
../mmc.c:128: error: 'SPI_MISO' undeclared (first use in this function)
../mmc.c:129: error: 'SPI_Clock' undeclared (first use in this function)
.
.
.
Ich denke, es fehlen ein paar einstellungen für den Controller. Aber ich 
weiss nicht wo und was...

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ich kenne die Atxmegas nicht.
Wie setzt man denn da einen Pin auf 1 bzw. 0 ?
In der mmc.h müssen die Pins an der die Karte hängt eingestellt werden.
Wenn aber bei einem xmega die Pins anders angesteuert werden müsste man 
da noch mehr anpassen...


Viele Grüße

Daniel

von XMEGA (Gast)


Lesenswert?

Hallo,

Uwe S. schrieb:
> fehlen ein paar Einstellungen für den Controller

in der mmc.h sind einige Atmega vordefiniert! Aber kein Atxmega.

Wenn du mit solchen Kaliebern arbeitest, solltest  du schon etwas 
Hintergrundwissen über die Hard- und Software besitzen.

Dir jetzt einen fertigen Code zuliefern ist nicht die richtige 
Vorgehensweise. Wenn dir der Befehl DDRB z.B. nichts sagt, ist das 
Betreiben einer SD-Card am XMEGA schon aussichtslos.

Sollte dennoch Intresse bestehen, melde dich nochmals.


Gruß GG

von Uwe S. (lan-opfer)


Lesenswert?

...nein - DDRB sagt mir jetzt so aus dem Kopf nix. Mit Atmels arbeite 
ich zum ersten mal. Ich habe vorher mit ARM9 (davor SAB509, PIC, ...) 
gearbeitet. Ich muss jetzt wohl hoffen,  dass mir der XMega dann nicht 
zu gross wird ;-)

@Daniel R.: bei den XMega ist die IO-Struktur neu gemacht - es gibt ein 
paar Register mehr. Ist hier ganz gut beschrieben:
http://www.stromflo.de/dokuwiki/doku.php?id=xmega-c-tutorial

von Daniel R. (zerrome)


Lesenswert?

Ok, sollte sich ganz einfach portieren lassen.
Schau ich mir später mal an.
Mit Deiner Hilfe Uwe S. wird das schon werden. Ich selber habe keine 
atxmega da.
Du könntest schon mal rausfinden an welchen Pins die SPI Schnittstelle 
liegt und in welchen Registern man die einstellt...

Viele Grüße

Daniel

von Uwe S. (lan-opfer)


Lesenswert?

...so - da bin ich wieder. Ich widme mich dem Thema nur sehr 
unregelmässig - je nachdem, wie ich Zeit habe.
In der mmc.h und der uart.h werden wohl durch die Compilerdirectiven die 
prozessorspezifischen Einstellungen vorgenommen - richtig? Ich denke, da 
müsste mann den XMega "reinzaubern".
"#if defined (_AVR_ATXmega64a3_)" oder so ähnlich - weisst du, wie das 
festgelegt werden muss?

An meinem Board ist ja der 64A3 drauf und für die SD-Karte wurde 
folgende Konfig. verwendet:
CS - PB1
MOSI - PC5
MISO - PC6
SCK - PC7
-> also SPIC

Als nächstes müsste ich deine Einstellungen mal vergleichen mit dem 
Manual:
http://www.atmel.com/dyn/resources/prod_documents/doc8077.pdf ab S. 229 
sind die Register beschrieben. Leider weiss ich nicht, in wie fern die 
sich mit dem ATMega decken.

LG

Uwe

von Daniel R. (zerrome)


Lesenswert?

Hallo,
also ich bin ab morgen erstmal ein paar Tage weg :)

Wegen
>#if defined (AVR_ATXmega64a3)
weiß ich selber nicht genau wie das mit den Xmegas geht, weiß aber hier 
sicher jemand anderes im Forum.

Also so wie ich das sehe, müsste in der mmc.h das in etwa so geändert 
werden:
1
  #define MMC_Write   PORTB  
2
  #define MMC_Read   PINB
3
  #define MMC_Direction_REG DDRB

zu
1
  #define MMC_Write   PORTC.OUT  
2
  #define MMC_Read   PORTC.IN
3
  #define MMC_Direction_REG PORTC.DIR

Jetzt ist das Problem, dass der CS Pin auch an Port C sein sollte, geht 
das irgendwie bei Deinem Board?
1
  #if defined (_AVR_ATXmega64a3_)
2
  #define SPI_MISO        6 
3
  #define SPI_MOSI        5 
4
  #define SPI_Clock     7  
5
  #define MMC_Chip_Select   (zusätzlicher Pin von PORTC) 
6
  #define SPI_SS        0
7
  #endif

Dann gibt es noch 2 Stellen in der mmc.c die geändert werden müssten
1
// hardware spi: bus clock = idle low, spi clock / 128 , spi master mode
2
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1);

und
1
//SPI Bus auf max Geschwindigkeit
2
SPCR &= ~((1<<SPR0) | (1<<SPR1));
3
SPSR |= (1<<SPI2X);

So wie ich das sehe, brauchst Du nur das Register CTRL vom Xmega. Dann 
sollte das laufen...

Viel Spass beim Basteln.

Bis die Tage dann

Viele Grüße

Daniel

von xmega (Gast)


Angehängte Dateien:

Lesenswert?

Servus,


Daniel R. schrieb:
> So wie ich das sehe, brauchst Du nur das Register CTRL vom Xmega. Dann
>
> sollte das laufen...

ich habe dir ein lauffähiges Projekt eingestellt.

Atxmega128a3, SPIC(SD-CARD), USART 115200 USARTF0

SPIC(SD-CARD) sollte auf allen XMEGA laufen!

Gruß xmega

von Buzzwang (Gast)


Lesenswert?

bei mir läuft es nun auch super. Vielen Dank für alles.
Die neue Version braucht viel weniger Platz (ca. 4kb) als die 0.5.9.
Es tuts auch der ATMEGA8
ATMEGA8 @ 8Mhz + 2GB SD-Card

von Friedrich K. (fiete)


Lesenswert?

Hallo.

Danke erstmal an Daniel für den Code!

In den Bemühungen den Code v.0.6.1 für eienn Mega8 auszudünnen, bin ich 
inzwischen bei 84% Speicherbelegung. Nur leider funktioniert es nicht, 
wenn ich LFN an und abschalte. Jednefalls ändert sich nach 
Neukompilierung nicht die Speichergröße.
Das zweite Problem hat wohl mit dem ersten zu tun. Ich habe den Plan 
eine START.TXT in Windows zu erzeugen, auslesen zu lassen und das in 
eine TEST.TXT (mehrmals) hineinzuschreiben. Nur für Testzwecke. Wenn ich 
mir das Ergebnis danach unter Windows anschaue, finde ich zwei 
START.TXT. Ich habe das Gefühl, dass er die Datei nochmal neu anlegt, 
wohl weil er die existierende nicht erkennt. Den Inhalt kann er aber 
lesen und schreibt ihn auch brav in die TEST.TXT

Was habe ich hier falsch gemacht?

Gruß, fiete

von Daniel R. (zerrome)


Lesenswert?

Hallo, bin wieder da :)

@ xmega (Gast)
Danke dafür, muss ich mir mal in ner ruhigen Minute zu Gemüt führen.

@ Friedrich K. (fiete)
Klingt nach Benutzerfehler. Man kann beispielsweise nicht 2 Dateien 
gleichzeitig öffnen. Poste mal den Code der bei Dir Probleme macht. Dann 
kann ich bestimmt mehr dazu sagen.

Viele Grüße

Daniel

von Friedrich K. (fiete)


Lesenswert?

Hey Daniel,

danke dass dus dir mal anschaust.
1
int main(void)
2
{
3
4
    DDRD=0xCC;
5
    PORTD=0xCC;        //0=beide an
6
                //4=linke an
7
                //8=rechte an
8
                //C=beide aus
9
  
10
  
11
12
  
13
14
  // Versuch Karte zu Initialisieren, bis es klappt. Umbedingt so, weil die Initialiesierung nicht immer auf anhieb klappt.
15
  while (FALSE==mmc_init())
16
    {
17
    nop();
18
    }
19
20
    PORTD=0xC8;
21
22
23
  // Fat initialisieren. Nur wenn das klappt sind weitere Aktionen sinnvoll, sonst aendet das Programm !
24
  if(TRUE == fat_loadFatData())
25
    {
26
    
27
    unsigned char start_dat[] = "START   TXT";
28
      
29
    //  if(MMC_FILE_EXISTS == ffileExsists(start_dat))
30
        {
31
        if(MMC_FILE_EXISTS == ffopen(start_dat))
32
        
33
          {
34
          
35
             // lesen eines chars und Ausgabe des chars.
36
              // solange bis komplette Datei gelesen wurde.
37
        
38
          for(i=0; i<19; ++i)
39
            {
40
            dat[i]=ffread();
41
            }
42
        
43
              ffclose();
44
          PORTD=0xC0;
45
        
46
             }
47
        }
48
      
49
  unsigned char file_name[]="LOG     TXT";
50
    
51
52
53
54
       // Datei existiert nicht, also anlegen !
55
      if(MMC_FILE_NEW == ffopen(file_name))
56
        {
57
58
       // Schreibt String auf Karte ! Nur richtige Strings koennen mit ffwrites geschrieben werden !
59
       ffwrites(dat);
60
61
       // Neue Zeile in der Datei
62
       ffwrite(0x0D);
63
       ffwrite(0x0A);
64
65
       // Schließt Datei
66
       ffclose();
67
       }
68
69
      // Datei existiert, also anhaengen !
70
      if(MMC_FILE_EXISTS == ffopen(file_name))
71
        {
72
73
       ffseek(file.length);   // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !
74
75
       // schreibt String
76
       ffwrites((unsigned char*)dat);
77
78
       // neue Zeile in der Datei
79
       ffwrite(0x0D);
80
       ffwrite(0x0A);
81
82
       // schließt Datei
83
       ffclose();
84
         }
85
       PORTD=0x00;
86
87
    }
88
89
}

Und ein Auszug aus der config.h, damit du weißt, was ich ein und 
ausgestellt hab.
1
  #define MMC_WRITE         TRUE  // TRUE, dann mit write unterstuetzung, wenn FALSE dann read only !
2
  #define MMC_OVER_WRITE       FALSE  // TRUE und MMC_WRITE TRUE, dann kann ffwrite dateien überschreiben, wenn FALSE dann nur normales schreiben. um an eine datei anzuhaengen ist MMC_OVER_WRITE TRUE nicht noetig!
3
  #define MMC_MULTI_BLOCK     FALSE  // TRUE und MMC_OVER_WRITE FALSE, dann werden multiblock schreib/lese funktionen benutzt. ist schneller, wird aber möglicherweise nicht von allen karten unterstützt. wenn FALSE ist normale operation
4
  #define MMC_SDHC_SUPPORT    FALSE  // TRUE, dann mit sdhc unterstuetzung, wenn FALSE, dann nur mmc/sd karten. siehe : http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29
5
  #define MMC_ENDIANNESS_LITTLE  TRUE  // TRUE, dann ist der code auf littleendian ausgelegt. AVR ist littleendian. code ist auf littleendian optimiert!! siehe: http://de.wikipedia.org/wiki/Endianness
6
  #define MMC_LFN_SUPPORT      FALSE  // TRUE, dann mit unterstuetzung fuer lange dateinamen. kostet wenn read und write benutzt wird um die 800 bytes flash...
7
  #define MMC_RM_FILES_ONLY    TRUE  // TRUE ,MMC_WRITE TRUE und MMC_RM TRUE, dann wird die funktion ffrm so mit kompiliert, dass sie nur dateien loeschen kann. wenn FALSE und MMC_WRITE TRUE, dann kann die funktion dateien und ordner rekursiv loeschen !
8
9
  // schalter die explizit funktionen mit kompilieren oder nicht!
10
  #define MMC_TIME_STAMP       FALSE   // TRUE, dann werden die funktionen fat_getTime und fat_getFreeBytes mit kompiliert. siehe auch abschnitt: ZEIT FUNKTIONEN, weiter unten
11
  #define MMC_RM           FALSE  // TRUE und MMC_WRITE TRUE, dann wird die funktion ffrm mit kompiliert.
12
  #define MMC_SEEK        TRUE  // TRUE,dann wird die funktion ffseek mit kompiliert. mit dieser funktion kann man in einer geoeffneten datei vor und zurueck spulen. nur in kombination mit MMC_OVER_WRITE TRUE kann in einer datei ueberschrieben werden.
13
  #define MMC_MKDIR        FALSE  // TRUE und MMC_WRITE TRUE, dann wird die funktion ffmkdir mit kompiliert. mit dieser funktion kann man ordner anlegen.
14
  #define MMC_GET_FREE_BYTES    FALSE  // TRUE, dann wird die funkton fat_getFreeBytes mit kompiliert. mit dieser funktion kann der freie platzt auf der karte ermittelt werden
15
  #define MMC_LS          FALSE  // TRUE, dann wird die funktion ffls mit kompiliert. mit dieser funkion kann man die dateien auf der karte anzeigen lassen
16
  #define MMC_CD          FALSE  // TRUE, dann werden die funktionen ffcd und ffcdLower mit kompiliert. mit diesen funktionen kann man in ein verzeichnis wechseln oder aus einem verzeichnis ein verzeichnis hoeher wechseln.
17
  #define MMC_FILE_EXSISTS    TRUE  // TRUE, dann wird die funktion ffileExsists mit kompiliert. mit dieser funktion kann geprueft werden, ob es die datei im aktuellen verzeinis gibt !
18
  #define MMC_WRITE_STRING    TRUE  // TRUE und MMC_WRITE TRUE, dann wird die funktion ffwrites mit kompiliert. mit dieser funktion koennen strings auf die karte geschrieben werden.


Ich habe mir ein paar LED's als Kontrolle eingebaut und der Code, so wie 
er ist, läuft zumindest danach zu urteilen durch. Ich muss dazu sagen, 
dass meine C-Kenntnisse auch eher dürftig sind...

Gruß, Fiete

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ohne den Code jetzt laufen zu lassen würde ich da schon ein paar Dinge 
als potentielle Probleme sehen.

Also das ist so ein Kandidat:
1
for(i=0; i<19; ++i)
2
{
3
   dat[i]=ffread();
4
}

das sollte besser "for(i=0; i<19; i++)" heißen. Dann sollte dat 
mindestens "unsigned char dat[20]" sein, weil du 19 Elemente und das 
'\0' speichern willst.

Dann noch:
1
ffwrites(dat);

Das funktioniert nur problemlos, wenn auf dat jetzt wirklich ein String 
steht. In C ist ein String immer mit '\0' terminiert, dafür musst Du 
sorgen. Ist das nicht so, schreibt die Funktion ffwrites Ram Inhalt auf 
die Karte bis sie auf eine 0 alias '\0' im Ram trifft.

Sonst sieht das eigentlich Ok aus.

Viele Grüße

Daniel

von Friedrich K. (fiete)


Lesenswert?

Danke Daniel,
das Array ist eigentlich richtig definiert, aber der letzte genannte 
Punkt könnte Probleme bereitet haben, das habe ich noch nicht bedacht. 
Ich probiere es mal aus...

Gruß, Fiete

von Friedrich K. (fiete)


Lesenswert?

Japp, fehlenden Terminal-zeichen lag es wohl. Ich bin nun ein ganzes 
Stück weiter, allerdings habe ich nun wieder Schwierigkeiten:

Es soll ein Datenlogger werden, der zwei Kanäle loggt und das auch in 
zwei files schreiben soll. Damit er nicht bei jedem furz schreibt, soll 
er erstmal pro Kanal 95Byte in den RAM schreiben, und dann den String 
aus dem RAM auf die Karte wegschreiben.

Also habe ich zwei Arrays definiert (und somit, wenn ichs recht verstehe 
auch den RAM reserviert):

unsigned char kanal_0 [95];
unsigned char kanal_1 [95];

in einer for-Schleife schreibe ich diese nun voll und wenn sie voll 
sind, dann wird ffwrites aufgerufen:
1
for(unsigned int j=0;j<20;j++)
2
        {
3
        kanal_0[j+w*20]=dat[j];
4
        }        
5
        
6
        w++;
7
        if(w==5)
8
        {
9
          // Datei existiert, also anhaengen !
10
            if(MMC_FILE_EXISTS == ffopen(filename_knal_0))
11
            {
12
          PORTD=0x80;           // <----- Fehlerkontrolleuchte
13
           ffseek(file.length);   // Spult bis zum Dateiende vor um anzuhaengen, geht auch ohne Option MMC_OVER_WRITE !
14
15
           // schreibt String
16
           ffwrites((unsigned char*)kanal_0);
17
18
          
19
           // schließt Datei
20
           ffclose();
21
22
          PORTD=0x00;           // <------ Fehlerkontrolleuchte
23
          w=0;           
24
          }

Analog für Kanal 1.

Wenn NUR Kanal 0 angesprochen wird, dann funktioniert das wunderbar,
wenn NUR Kanal 1 angesprochen wird auch, aber wenn beide angesprochen 
werden, dann ist eine der beiden Files meist nicht mehr lesbar und die 
Strings in der Datei haben kaputte Stellen drin (irgendwelche Zeichen, 
die da nicht hingehören). Das pikante ist, dass das Problem wohl nicht 
im RAM auftritt, denn wenn ich z.B. 5x von kanal 1 auf die SD-Karte 
schreibe, und dann einmal von kanal 2, dann treten Fehler an Stellen 
auf, die vorher schon geschrieben wurden. Daher vermute ich, dass die 
FAT irgendwie Probleme macht oder ich irgendetwas anderes nicht bedacht 
habe...

Interrupts kommen eigentlich auch nicht in Frage für das Problem, weil 
ich erst wieder die Kanäle auslese, wenn alles andere abgeschlossen ist.

Jetzt hab ich überlegt, dass der Stack eventuell Probleme machen könnte, 
aber ich bin ja noch knapp 300Byte übrig für den Stack. Ich kann mir 
nicht vorstellen, dass das Probleme bereitet.

Ein weiters Problem ist, dass der Controller nur Dateinen beschreiben 
kann, die er selber angelegt hat, und auch leider nicht mehr nach einer 
Neuinitialisierung. D.h. ich muss die kanal.txt immer löschen, bevor ich 
das Programm nochmal duchlaufen lassen kann. Könnte es vielleicht auch 
damit zusammenhängen?

Bin für Tipps dankbar.

Besten Gruß aus Heidelberg,
fiete

von Daniel R. (zerrome)


Lesenswert?

Hallo,
also eigentlich puffert die Lib schon. Um genau zu sein 512 Bytes, da 
das genau ein Sektor ist. Da könntest Du Dir den ganzen Quatsch mit dem 
Puffern der Kanäle sparen.

Das ist so gefährlich
1
for(unsigned int j=0;j<20;j++)
2
    {
3
    kanal_0[j+w*20]=dat[j];
4
    }
Wenn w 5 ist und j 20, dann ist 20+5*20 = 120, also deutlich über der 
Array Grenze hinaus. Damit überschreibst Du was weiß ich im Ram...

Was für Daten kommen den so vor bei den Kanälen? Falls da Steuerzeichen 
vorkommen, also z.B. integer 0, dann geht das mit ffwrites NICHT.
Also noch mal ganz deutlich: NUR Strings sollten mit ffwrites 
geschrieben werden! Ein String wird mit '\0' terminiert. Also Ascii Code 
Buchstaben und Zahlen im Ascii Code quasi.

Mein Vorschlag wäre im http://de.wikipedia.org/wiki/CSV_(Dateiformat) 
Format die beiden Kanäle in eine Datei zu schreiben, aber in zwei 
Spalten in der Datei. Dann brauchst Du Dir um puffern keine Gedanken 
mehr zu machen, da das ja schon die Lib macht.

>Ein weiters Problem ist, dass der
>Controller nur Dateinen beschreiben
>kann, die er selber angelegt hat...

Ich vermute das Programm kommt vorher schon durcheinander, oder der 
Dateiname entspricht nicht den Konventionen.

Viele Grüße

Daniel

von Daniel R. (zerrome)


Lesenswert?

Hallo Friedrich K.,
wie läuft es? Gibt es Fortschritte?

Viele Grüße

Daniel

von Friedrich K. (fiete)


Angehängte Dateien:

Lesenswert?

Hey Daniel,

sehr nett, dass du nachfragst. Aber leider funktionierts noch nicht 
zufriedenstellend. Habe mir mal den Beispielcode geschnappt und 
stückchenweise modifiziert. Die Idee war dann tatsächlich mit ffwrite 
(ohne s) wegzuschreiben und zwar auf knopfdruck == trigger.

Es bleiben dabei zwei Probleme: Ich habe es immernoch nicht geschafft 
ausser beim Beispielcode eine Datei nach dem entnehmen der Karte und 
neuinitialisierung wieder zu öffen und zu beschreiben.
Das zweite Problem ist mehr eine Frage. Ich konnte nicht ganz ausmachen, 
an welcher Stelle des Codes wirklich echt vom RAM auf die Karte 
geschrieben wird. Denn ich würde gern auf Knopfdruck ebenfalls den rest 
der im RAM steht, auf die Karte schreibt, sodass man sie entnehmen kann. 
Wenn ich das recht sehe, dann tut das ffclose nicht allein, sondern 
setzt nur die Flags null.

Am besten poste ich mal wie ich den Beispielcode modifiziert habe. 
Vielleicht ist da was schief gelaufen, was ich nicht seh...

Was du da siehst, ist meine "wunsch-Konfiguration". Sie funktioniert 
nicht. Habe vorher Stückchenweise ausprobiert und sobald ich das ffclose 
auf knopfdruck aufrufe, funktionierts nicht mehr. Die Datei kann nicht 
gelesen werden unter windows (beschädigt) es wird aber eine realistische 
größe angezeigt.
1
    while(1)
2
    {
3
      if(!((PINC&0x01)==0x01))
4
      {
5
        if((PINC&0x01)==0x01)  //<<---- Erst beim Loslassen schreiben.
6
        {
7
             // Datei existiert, also anhaengen !
8
            if(MMC_FILE_EXISTS == ffopen(file_name))
9
            {
10
            
11
             // bewusst kein ffseek, weil ja, nicht geschlossen und Flags noch gesetzt
12
13
             // schreibt "String" Alternativ While Schleife
14
             ffwrite(48);
15
             ffwrite(49);
16
             ffwrite(50);
17
             ffwrite(51);
18
             ffwrite(52);
19
             ffwrite(53);
20
             ffwrite(54);
21
             ffwrite(55);
22
             ffwrite(56);
23
             ffwrite(51);
24
             
25
26
            
27
             // neue Zeile in der Datei
28
             ffwrite(0x0D);
29
             ffwrite(0x0A);
30
31
             /// Bewusst kein ffclose, da erst auf knopfdruck schließen soll
32
             
33
            }
34
          }
35
        
36
      }
37
      if(!((PINC&0x04)==0x04))  // <<--- Kontroll LED
38
      {
39
      ffclose();
40
      PORTD=0xCC;
41
      }
42
    }

Aber Fortschirtte gibts schon. Das ganze soll ein Wasserzähler werden 
der kalt und Warmwsser loggt. Die alte ochsentour mit dem 
selbstdefinirtem RAM hat ja einigermaßen fuktioniert, sodass ich ihn 
schon 24h hab laufen lassen können. Hab mal das Histogramm angehängt ;-)

Gruß, Fiete

von Daniel R. (zerrome)


Lesenswert?

Hallo.

>Ich habe es immernoch nicht geschafft
>ausser beim Beispielcode eine Datei nach
>dem entnehmen der Karte und
>neuinitialisierung wieder zu öffen und zu beschreiben.

Ich vermute mal, dass Du bevor Du die Karte entfernst nicht ffclose 
aufrufst. Mach es doch so, dass Du eine LED einschaltest wenn Du ffopen 
aufrufst und aus, wenn du ffclose aufrufst. So kannst Du genau sehen ob 
die Datei geöffnet oder geschlossen ist.

>Ich konnte nicht ganz ausmachen,
>an welcher Stelle des Codes wirklich
>echt vom RAM auf die Karte...

Bei einem fflushFileData() wird alles was aktuell im Ram ist auf die 
Karte geschrieben. Zudem wird der Dateieintrag geupdatet. Das ist 
prinzipiell ein ffclose(), nur dass die Datei danach nicht neu geöffnet 
werden muss um weiter zu schreiben. Sollte aber so selten wie möglich 
aufgerufen werden, da viele Schreiboperationen auf der Karte gemacht 
werden.

Sind die Taster ordentlich entprellt? Vielleicht geht da einiges 
durcheinander.

So wie ich das sehe, öffnest Du die Datei mehrfach, bevor Du sie 
schließt.
Versuch mal das:
1
   if(MMC_FILE_EXISTS == ffopen(file_name))
2
   {
3
      // Datei existiert, also zum Ende spulen
4
      ffseek(file.length);
5
6
      // hier Status LED an
7
   }
8
9
   while(1)
10
   {
11
      // Pin1 gedrückt?
12
      if(!((PINC&0x01)==0x01))
13
      {
14
         // hier warten bis Taste losgelassen wird!
15
         while( !((PINC&0x01)==0x01) );;
16
17
         // schreibt "String" Alternativ While Schleife
18
         ffwrite(48);
19
         ffwrite(49);
20
         ffwrite(50);
21
         ffwrite(51);
22
         ffwrite(52);
23
         ffwrite(53);
24
         ffwrite(54);
25
         ffwrite(55);
26
         ffwrite(56);
27
         ffwrite(51);
28
29
         // neue Zeile in der Datei
30
         ffwrite(0x0D);
31
         ffwrite(0x0A);        
32
      }             
33
34
      // Pin4 gedrückt?
35
      if(!((PINC&0x04)==0x04))  
36
      {
37
         ffclose();
38
39
         // Status LED hier aus, alles OK. Karte kann entfernt werden!
40
41
         break;   // um aus endlosschleife zu kommen
42
      }
43
44
  }


Ohne den Code so laufen zu lassen, denke ich sollte das gehen.

Hoffe irgendwas hiervon hilft :)

Viele Grüße

Daniel

von Friedrich K. (fiete)


Lesenswert?

Hey Daniel, danke für deine Antwort. Ich werds gleich heute abend mal 
ausprobieren.

Zum Prellen: ich habe mir eigentlich entprellte Taster besorgt. Lese 
gerade, dass man da noch Vorkehrungen treffen muss. Ich bin bisher immer 
davon ausgegangen, das es bei entprellten tastern kein Problem ist... 
Vielleicht hat er bei ffclose deshalb probleme bekommen...

Zu Kontroll LEDs: Ja, hab kontroll LEDs eingefügt, bei denen ich seh, wo 
er grad ist. Ich konnte sogar sehen, dass er auf die Karte geschrieben 
hat, weil er dann läger im ffwrite war und so die LED nen bissel länger 
geleuchtet hatte. In dem code den ich dir schickte, sind die LEDs nur 
noch zum teil drin. Ich schiebe die immer rum im code, um zu gucken, wo 
er grad "hängt".

Zu ffclose: Stört es, wenn ffclose mehrfach aufgerufen wird? Weil die 
Verrenkung dass er erst beim Losassen aus der Schleife steigt, hab ich 
mir bei ffclose gespart.

Zu fflushFileData: Muss man danach noch ffclose aufrufen? Wenn ichs 
recht sehe ja.

Kann es eventuell sein, dass die Karte einen knacks hat?

Ich werde wie gesagt mich heute Abend mal damit auseinander setzen und 
bericht erstatten.

Danke nochmal.

Gruß, Fiete

von Daniel R. (zerrome)


Lesenswert?

Hallo.

>...Verrenkung dass er erst beim
>Losassen aus der Schleife steigt...

Die Verrenkung ist doch nur ein "break;" um aus der Schleife raus zu 
kommen. Ob jetzt bei Taste gedrückt oder losgelassen ist ja nur die 
Abfrage im if...

>Stört es, wenn ffclose mehrfach aufgerufen wird?

Eigentlich nicht, ist aber unnötig. Muss halt so programmiert werden das 
es nicht vor kommt :)

>Zu fflushFileData: Muss man danach
>noch ffclose aufrufen? Wenn ichs
>recht sehe ja.

fflushFileData ist eigentlich dazu gedacht, dass wenn ein Gerät z.B. 
über Tage läuft und Daten loggt, man zwischendurch mal zur Sicherheit 
fflushFileData aufruft. So hat man die Daten bis dahin schonmal 
gesichert, falls der Strom ausfällt oder ähnliches. Dadurch spart man 
sich ein ffclose und ffopen.


Funktioniert die Karte denn unter Windows noch ordentlich? Also 
beschreibbar, lesbar und keine Fehler beim Formatieren? Wenn es da keine 
Probleme gibt, sollte die Karte noch OK sein.



Viele Grüße

Daniel

von Lukas L. (lukas5)


Lesenswert?

Hallo.
Ich bin hier neu im Forum und habe bis jetzt nicht so viel Erfahrung mit 
AVRs. Deswegen bitte sich nicht über meine dummen Fragen ärgern.

Ich werde mein Atmega32L mit 3,3V versorgen und mit 8MHz takten. Meine 
Karte hat 2GB. Ich möchte Fat32 benutzen.

Soll sie zuerst mit dem PC mit FAT32 formatiert werden oder macht das 
dein Programm?
Kanst du mir bitte sagen an welche Pins des Atmega32 ich die SD Karte 
anschliesen muss?
Wo soll ich im Code eine Umstellung von Fat16 auf Fat32 machen?
Mit welcher Funktion wird eine neue Datei erzeugt?
Mit welcher Funktion wird eine Datei beschrieben?

Grüße,
Lukas

von Friedrich K. (fiete)


Lesenswert?

Hey Lukas,

also das mit den SD-Karten ist nicht so ganz ohne. Du solltest schon 
mindestens nen bisschen C mitbringen und das AVR Tutorial wäre auch 
nicht schlecht, einfach, damit du nen bissel weißt, was du tust. Es ist 
jedenfalls im seltensten Fall so, dass man es einschaltet und alles 
funktioniert. Guck dir mal in der Artikelübersicht 
http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten da steht 
schonmal ne Menge drin.

Gruß, fiete

von Lukas L. (lukas5)


Lesenswert?

Hallo.
Man verwendet Belegung wie sie in der "mmc-0.2.H" Datei angegeben ist. 
Habe ich das richtig verstanden? Warum wird denn der SPI-Port für den 
Anschluss verwendet. Das ist doch unpraktisch, jedesmal die Karte 
auszustecken um zu programmieren??
Hast du deine Karte auch an PORTB abgeschlossen?

Grüße,
Lukas

von Friedrich K. (fiete)


Lesenswert?

Der SPI-Port stehllt das Protokoll bereit, das mit der Karte 
kommuniziert. Das ist eine Bus-Kommuikation. Es können also mehrere 
Bauteile angeschlossen werden und nur das, welches aktivirt ist, fühlt 
sich auch angesprochen. Aktivirt wird wenn ichs richtig im kopf hab wenn 
pin 0 auf high gezogen wird...

von Daniel R. (zerrome)


Lesenswert?

Hallo Lukas.

Hier gibt es auch noch mehr Informationen
http://www.mikrocontroller.net/articles/AVR_FAT32

Die neuste Version ist immer unter
http://www.mikrocontroller.net/svnbrowser/avr-fat32
zu bekommen.

Dabei ist auch ein Beispiel Programm wo die Benutzung gezeigt wird.

Viele Grüße

Daniel

von Kurt B. (kurt)


Lesenswert?

Ich versuche gerade die Software mit Keil µVision4 auf einen LPC2148 zu 
portieren. Der Compiler spuckt aber Fehler aus. Da soll wohl noch was 
umgecastet werden?
1
fat.c(120): error:  #852: expression must be a pointer to a complete object type
2
fat.c:                  vsector+=   6;
3
fat.c:                  ^
4
fat.c(123): error:  #852: expression must be a pointer to a complete object type
5
fat.c:                  vsector+=2;
6
fat.c:                  ^
7
fat.c(422): error:  #852: expression must be a pointer to a complete object type
8
fat.c:                          *(unsigned char*)vsector++ = 0x00;
9
fat.c:                                           ^
10
fat.c(431): error:  #852: expression must be a pointer to a complete object type
11
fat.c:                          *(unsigned char*)vsector++ = toupper(name[i]);
12
fat.c:                                           ^
13
fat.c(439): error:  #852: expression must be a pointer to a complete object type
14
fat.c:          vsector++;
15
fat.c:          ^
16
fat.c(478): error:  #852: expression must be a pointer to a complete object type
17
fat.c:                  vsector+=8;
18
fat.c:                  ^
19
fat.c(482): error:  #852: expression must be a pointer to a complete object type
20
fat.c:                  vsector+=6;
21
fat.c:                  ^
22
fat.c(486): error:  #852: expression must be a pointer to a complete object type
23
fat.c:                  vsector+=2;
24
fat.c:                  ^

1
void fat_loadRowOfSector(unsigned short row){
2
3
  #if (MMC_ENDIANNESS_LITTLE==TRUE)
4
    void *vsector;                  // voidpointer, damit man schoen umbiegen kann :)
5
6
    vsector=&fat.sector[row+20];          // row ist byteoffset einer reihe
7
8
    file.firstCluster=*(unsigned short*)vsector;  // high word von first.cluster (20,2)
9
    file.firstCluster=file.firstCluster<<16;
10
    
11
    vsector+=   6;
12
13
    file.firstCluster|=*(unsigned short*)vsector;  // low word von first.cluster (26,2)
14
    vsector+=2;
15
16
    file.length=*(unsigned long int*)vsector;    // 4 byte von file.length (28,4)
17
  #else
18
    unsigned char *psector =& fat.sector[row+31];
19
20
    file.length =  *psector--;    // 31    hoechstes byte
21
    file.length <<= 8;
22
    file.length |=  *psector--;    // 30
23
    file.length <<= 8;
24
    file.length |=  *psector--;    // 29
25
    file.length <<= 8;
26
    file.length |=  *psector;    // 28
27
28
    psector-=7;
29
    file.firstCluster =  *psector--;          // 21  hoechstes byte
30
    file.firstCluster <<= 8;
31
    file.firstCluster = file.firstCluster | *psector;  // 20
32
    file.firstCluster <<= 8;
33
34
    psector+=7;
35
    file.firstCluster = file.firstCluster | *psector--;  // 27
36
    file.firstCluster <<= 8;
37
    file.firstCluster = file.firstCluster | *psector;  // 26
38
  #endif
39
}
1
void fat_makeSfnDataEntry(unsigned char name [],unsigned char attrib,unsigned long int cluster,unsigned long int length){
2
3
  unsigned char i;       // byte zähler in reihe von sektor (32byte eintrag)
4
  void *vsector;         // void zeiger auf sektor, um beliebig casten zu können
5
  unsigned short row;    // reihe in dem sektor
6
7
  fat.bufferDirty = TRUE;   // puffer beschrieben, also neue daten darin(vor lesen muss geschrieben werden)
8
  row = file.row;
9
  row = row<<5;        // multipliziert mit 32 um immer auf zeilen anfang zu kommen (zeile 0=0,zeile 1=32,zeile 2=62 ... zeile 15=480)
10
  vsector =& fat.sector[row];  // anfangs adresse holen ab der stelle auf sector geschrieben werden soll
11
12
  #if (MMC_TIME_STAMP==TRUE)
13
    unsigned char new=FALSE;
14
    // pruefung ob eintrag neu ist.
15
    if(fat.sector[row]==0xE5||fat.sector[row]==0x00)   new=TRUE;
16
  #endif
17
18
  #if (MMC_TIME_STAMP==FALSE)
19
    // alle felder nullen...
20
    i = 20;
21
    do{
22
      *(unsigned char*)vsector++ = 0x00;
23
    }while( i-- );
24
    vsector =& fat.sector[row];
25
  #endif
26
27
  // namen schreiben (0,10)
28
  i = 0;
29
  do{
30
    #if (MMC_LFN_SUPPORT==TRUE)
31
      *(unsigned char*)vsector++ = toupper(name[i]);
32
    #else
33
      *(unsigned char*)vsector++ = name[i];
34
    #endif
35
  }while( ++i < 11);
36
37
  // attrib schreiben (11,1)
38
  *(unsigned char*)vsector = attrib;
39
  vsector++;
40
41
  #if (MMC_TIME_STAMP==TRUE)
42
    unsigned short time=fat_getTime();
43
    unsigned short date=fat_getDate();
44
45
    // reserviertes byte und milisekunden der erstellung (12,2)
46
    *(unsigned short*)vsector=0x0000;
47
    vsector+=2;
48
49
    if(new==TRUE){
50
      // creation time,date (14,4)
51
      *(unsigned long int*)vsector=date;
52
      *(unsigned long int*)vsector=*(unsigned long int*)vsector<<16;
53
      *(unsigned long int*)vsector|=time;
54
    }
55
    vsector+=4;
56
57
    // last access date (18,2)
58
    *(unsigned short*)vsector=date;
59
    vsector+=2;
60
61
    // low word von cluster (20,2)
62
    *(unsigned short*)vsector=(cluster&0xffff0000)>>16;
63
    vsector+=2;
64
65
    // last write time,date (22,4)
66
    *(unsigned long int*)vsector=date;
67
    *(unsigned long int*)vsector=*(unsigned long int*)vsector<<16;
68
    *(unsigned long int*)vsector|=time;
69
    vsector+=4;
70
71
    // high word von cluster (26,2)
72
    *(unsigned short*)vsector=(cluster&0x0000ffff);
73
    vsector+=2;
74
75
    // laenge (28,4)
76
    *(unsigned long int*)vsector=length;
77
  #else
78
    vsector+=8;
79
80
    // low word  von cluster (20,2)
81
    *(unsigned short*)vsector=(cluster&0xffff0000)>>16;
82
    vsector+=6;
83
84
    // high word von cluster (26,2)
85
    *(unsigned short*)vsector=(cluster&0x0000ffff);
86
    vsector+=2;
87
88
    // laenge (28,4)
89
    *(unsigned long int*)vsector=length;
90
  #endif
91
}

von Daniel R. (zerrome)


Lesenswert?

Hallo,
versuch mal "#define MMC_ENDIANNESS_LITTLE FALSE" in der config.h
Damit fliegen überall die void Pointer raus. Ist aber evtl. nicht so 
schnell dann.

Es gibt da mit mehreren Kompilern Probleme wegen void Pointern. Verstehe 
ich nicht ganz, weil das eigentlich normaler C Standard sein sollte...

Viele Grüße

Daniel

von Matze N. (hupe123)


Lesenswert?

Hi,

ich hab da auch mal wieder ne Frage.
Ich will mit der neuen Version (0.6.1) einen Ordner anlegen. In der 
Config.h ist #define MMC_LFN_SUPPORT            TRUE. So weit, so gut!
Aber wenn ich nun alle:
1
unsigned char datum_verzeichnis[8];    //Beispiel: "33-33-33
2
datum_verzeichnis[0] = datum[0];
3
datum_verzeichnis[1] = datum[1];
4
datum_verzeichnis[2] = '-';        
5
datum_verzeichnis[3] = datum[3];        
6
datum_verzeichnis[4] = datum[4];        
7
datum_verzeichnis[5] = '-';
8
datum_verzeichnis[6] = datum[6];
9
datum_verzeichnis[7] = datum[7];        
10
11
ffmkdir(datum_verzeichnis);
12
ffcd(datum_verzeichnis);
ein Verzeichnis anlegen will, dann geht das nicht. Windoofs will da wohl 
am ende der Eingabe noch ein abschließedendes Zeichen haben. Kann mir 
bitte jemand verraten, welches das ist?
Und mit einem HEX-Editor kann ich leider kein Verzeichnis öffnen... Bei 
normalen Dateien kann man ja "spicken" wie bestimmte Steuerzeichen 
aussehen. Bei Ordner geht das nich...

Danke für alle guten Tipps!
Matze

von Kurt B. (kurt)


Angehängte Dateien:

Lesenswert?

Danke Daniel. Das lesen von Dateien geht jetzt ohne Probleme. Aber beim 
fclose nach dem schreiben in eine Datei bleibt er hängen. Ein Hardware 
Problem schließe ich aus, da das lesen funktioniert. Timing Probleme 
dürften es auch nicht sein da ich den Prozessor bis auf 12MHz 
runtergetaktet habe.

Im Anhang ist das komplette µVison Projekt, lauffähig mit debug 
Ausgaben, und die debug Meldungen. Er bleibt ganz am Schluss zwischen 
Kontrollpunkt D und E hängen, obwohl er vorher mehrmals korrekt bis E 
durchläuft.

Ich höffe es ist einigermaßen verständlich was ich meine. ;-)


Mfg,
Kurt


PS: Ich habe die Software auch auf einem Mega32 mit 18,x MHz getestet, 
da funktionieren lesen und schreiben wunderbar!

von Kurt B. (kurt)


Angehängte Dateien:

Lesenswert?

Das war natürlich die falsche Datei!
@Moderatoren: bitte löschen.

Hier kommt die richtige.

von Matze N. (hupe123)


Lesenswert?

so gehts:
1
unsigned char datum_verzeichnis[9];    //Beispiel: "33-33-33
2
datum_verzeichnis[0] = datum[0];
3
datum_verzeichnis[1] = datum[1];
4
datum_verzeichnis[2] = '-';        
5
datum_verzeichnis[3] = datum[3];        
6
datum_verzeichnis[4] = datum[4];        
7
datum_verzeichnis[5] = '-';
8
datum_verzeichnis[6] = datum[6];
9
datum_verzeichnis[7] = datum[7];
10
datum_verzeichnis[8] = 0x00;        
11
12
ffmkdir(datum_verzeichnis);
13
ffcd(datum_verzeichnis);

Aber da muss man erstmal drauf kommen... ;)

von Kurt B. (kurt)


Lesenswert?

Leider waren doch meine SPI (SSP) Funktionen falsch! Also bitte meine 
beiden letzten Beiträge ignorieren.

ABER: In der fat_loadSector() ist anscheinend ein return FALSE zuviel?

Mfg,
Kurt

von Daniel R. (zerrome)


Lesenswert?

Hallo zusammen.
Wunderbar, dass sich hier alles von selber erledigt :)
Hm, das FALSE da ist wirklich überflüssig... da kommt man ja garnicht 
hin.
Wird geändert.

Viele Grüße

Daniel

von max (Gast)


Lesenswert?

Funktioniert der Code auch auf einen ATmega162?
was muss ich dafür im Makefile ändern?

von Daniel R. (zerrome)


Lesenswert?

Hallo max,
Du musst im Makefile bei

# MCU name
MCU = atmega162

eintragen.

Dann noch in der mmc.h die Pins der Hardware SPI Schnittstelle 
eintragen.
1
  #if defined (__AVR_ATmega162__)
2
  #define SPI_MISO        6  //Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist
3
  #define SPI_MOSI        5  //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist
4
  #define SPI_Clock       7  //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk)
5
  #define MMC_Chip_Select   0  //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist
6
  #define SPI_SS          4  //Nicht Benutz muß aber definiert werden
7
  #endif

Viele Grüße

Daniel

von little man (Gast)


Lesenswert?

Hallo,
erstmal: Super Arbeit!

Leider läuft das Schreiben auf die SD-Karte nur sehr langsam.
Ca. 4kB/s! Auf dem Osi sieht man, dass er manchmal 200ms brauch um auf 
die Karte zu schreiben.

Aber die Datei wird fehlerfrei geschrieben.

Hat jemand eine Ahnung wodran das liegen könnte, ich verzweifle dran?
Habe schon verschiedene SD-Karten ausprobiert, Takt geändert,  immer das 
gleiche Problem!

Daten:
Atmega88 @7.3728Mhz @3,3V

von Matze N. (hupe123)


Lesenswert?

das problem hab ich auch manchmal. versuch mal ne andere SD-Karte.
Wenn ich mal ausversehen die SD-Karte im Slot habe, wenn der ISP dran 
is, dann kriegt sie wohl einen "Schaden". In anderen Geräten geht sie 
dann noch, aber am µC nich mehr. Ich weiß auch nicht, woran das liegt. 
Is halt mein "Word-Around"... Nich schön, weil auf dauer teuer, aber was 
will man machen ;)

von Matze N. (hupe123)


Lesenswert?

Hmm... habe mich wohl geirrt! Sorry!
Ich hatte ja das selbe Problem: mals liefs und mal nicht. Ich habe immer 
mit WinAVR compiliert und bin gestern einfach mal spaßeshalber in das 
AVR Studio gewechselt und habe da den selben Code compiliert - jetzt 
geht alles und zwar immer... also, wenn du mit dem WinAVR arbeitest: 
wechseln ;)

von Daniel R. (zerrome)


Lesenswert?

Hallo,
kann mir eigentlich nur vorstellen, dass es mit Kompiler Optionen zu tun 
hat oder etwas in dieser Richtung. Vielleicht ist es aber auch wenn das 
nur bei einer Karte auftritt eine extrem langsame. Habe hier auch eine 
16MB Karte die extrem langsam ist.

Grüße

Daniel

von Matze N. (hupe123)


Lesenswert?

Naja, ich habe am Versuchsaufbau nichts geändert! Sogar die selbe Karte 
benutzt. Mit dem ARV Studio geht es nun aber flüssig und vor allem 
immer.
Is komisch, ist aber so.

von little man (Gast)


Lesenswert?

Hallo,

danke für die Anregungen.
Ich arbeite nur mit Avr Studio, also daran lag es nicht.

Habe mal ne ganze Menge an Karten ausprobiert und gemessen. Habe 
festgestellt, dass die Noname Karten am Besten funktionieren.

Habe die Benchmark bißchen umgeschrieben. Schreibe 196k-Datein und davon 
100 Stück und messe die einzelnen Zeiten! Folgende Ergebnisse:

ScanDisk SD 2Gb (neu):
3.2s für die 1.Datei
10s für die 100. Datei

SD-Formel1 256Mb (hab ich irgendwo ausgegraben):
2,6s für die 1.Datei
2,4s für die 100. Datei

NONAME SD-micro 2Gb (aus meinem Handy)
3.6s für die 1.Datei
3.4s für die 100. Datei

CN Memory SD 8Gb mit SD_HC Support (neu)
3.2s für die 1.Datei
25s für die 100. Datei

Hab da noch paar Karten getestet. Manche werden halt sehr lahm! Hab 
keine Ahnung wodran das liegt, benutze einfach die Karten die durchweg 
schnell schreiben. Das sind die Karten die sich mit FAT 16k formatieren 
lassen. Keine Ahnung, ob das damit zusammen hängt??? Bin noch Laie auf 
dem Gebiet!

Welche Karten würdet ihr denn empfehlen? Sind MMC Karten schneller?

von little man (Gast)


Lesenswert?

Ich sollte vielleicht noch folgendes erwähnen:

Atmega88 @3.3V @7,3728MHz

von Daniel R. (zerrome)


Lesenswert?

Hallo,
stimmen diese Daten?

>SD-Formel1 256Mb (hab ich irgendwo ausgegraben):
>2,6s für die 1.Datei
>2,4s für die 100. Datei

>NONAME SD-micro 2Gb (aus meinem Handy)
>3.6s für die 1.Datei
>3.4s für die 100. Datei

Die werden schneller bei 100 Dateien?!?
Zeig mal den Benchmark Code !

Ja MMC Karten sind deutlich schneller, keine Ahnung wieso.

Fat16 zu Fat32 macht bei mir keinen so großen Unterschied. Ist im 
einstelligen KB Bereich.
Ob ich Multiblock ein/aus schalte macht deutliche Unterschiede.

Deine maximale SPI Geschwindigkeit ist f_cpu / 2 also 7,3728 MHz / 2 = 
3,6864 MHz. Das ist jetzt nicht so wahnsinnig schnell. Die Karten sind 
für 25 MHz ausgelegt.

Was willst Du denn eigentlich speichern? Muss das so schnell sein?

Viele Grüße

Daniel

von little man (Gast)


Angehängte Dateien:

Lesenswert?

Hey,

hab jetzt noch paar MMC Karten getestet, lassen sich so mit 77kB/s 
beschreiben. Ich glaub ich werde nun nur MMC benutzen! Funktionieren 
alle durchgehend gut.

Daniel R. schrieb:
> Die werden schneller bei 100 Dateien?!?
> Zeig mal den Benchmark Code !

Hab die benchmark angehängt.
Fand ich auch komisch. Dies tritt nur auf, wenn die Karte formatiert und 
relativ alt ist. Sind da schon Daten drauf, schreibt sie durchgehend 
konstant. Kann sein das die ersten Sektoren schon beschädigt sind!?

Hab mir jetzt mal ein größeren Controller bestellt. Wird mir hier 
einbisschen eng auf dem Atmega88. Dann drehe ich auch die Frequenz auf 
16MHz.

Daniel R. schrieb:
> Was willst Du denn eigentlich speichern? Muss das so schnell sein?

Muss Strom und Spannung mit 2.5kS/s abtasten und ablegen. Desto 
schneller ich speichern kann, desto weniger muss ich Puffern.

Bis dann und vielen Dank für den bereitgestellten Code!

von Matze N. (hupe123)


Lesenswert?

Hi,

ich habe eine Frage zu deinem Benchmark.
Kannst du mir mal bitte die Zeite
1
c = c==254 ? 0 : c;
 erklären. Ich kenne weder ein "?" noch ein ":" in einer Zeile. Nur 
interesse halbe (ich lerne immer wieder was dazu ;)

Liebe Grüße,
Matze

von Bad U. (bad_urban)


Lesenswert?

Hallo,

das ist eine verkürzte Schreibweise für eine Abfrage. Wenn C=254 wird c 
der Wert hinter dem Fragezeichenzugewiesen. Wenn nicht der Wert hinter 
dem : Allerdings bin ich der Meinung, dass es am Ende :c++ heissen 
müsste. Ich kenne das Programm nicht, aber das soll wohl eine 
Zählvariable sein. Kann aber auch sein, dass sie woanders im Programm 
verändert wird. Dann macht diese Art der Abfrage allerdings weniger 
Sinn...

Gruß
Bad Urban

von Matze N. (hupe123)


Lesenswert?

Cool! Wieder was gelernt!!!
Ich habe mal in der Quelltext geschaut, das müsste wirklich ":c++;" 
heißen.

Danke aber fürs übersetzen!!
Gruß,
Matze

von Bad U. (bad_urban)


Lesenswert?

Freut mich wenn ich helfen kann. Bin da das erste mal auch mit großen 
Augen davor gesessen :-)

von holger (Gast)


Lesenswert?

>Ich habe mal in der Quelltext geschaut, das müsste wirklich ":c++;"
>heißen.


Nö.

>      ffwrite(c++);
>      c = c==254 ? 0 : c;

Fällt euch was auf?

Das ist eine kryptische Schreibweise für ein if{}else{}
Sowas gehört in kein C Programm.

von Matze N. (hupe123)


Lesenswert?

Ok, das "ffwrite(c++);" hab ich übersehen. Mein Fehler.

Aber warum sollte ein "c = c==254 ? 0 : c;" nicht in ein c-Programm? 
Vorallem die Begründung, daß es kryptisch sei halte ich für arg 
schwammig. Ich denke, ich werde es zu meinem Standart für solche Fälle 
erklären. Warum sollte ich das nicht dürfen?! Ich finds kurz und 
prägnant.

von hm (Gast)


Lesenswert?

so kann der kompiler auf jeden fall besser optimieren als bei einem 
if/else
und es ist ja schon standard c

von Daniel R. (zerrome)


Lesenswert?

Hallo.

@little man (Gast)

Die interessanten Teile hast Du weggelassen :)
Wie sehen folgende defines bei Dir aus?
1
#define TOP_OCR 0xF9
2
#define START_TCNT 0x06
3
#define PRESCALER 0x03

von little man (Gast)


Lesenswert?

Hey,

hab die defines auf mein CPU Takt angepasst!
Ansonsten, wie gesagt, kaum was an deiner Benchmark verändert.

#define TOP_OCR 0x7A
#define START_TCNT 0x06
#define PRESCALER 0x03

Bis dann!

von Daniel R. (zerrome)


Lesenswert?

Hallo,
also mein Timer Rechner sagt mit einer Frequenz von 7.3728 MHZ müssen 
die Werte bei einem Überlauf von 1 ms:
1
#define TOP_OCR 0x72
2
#define START_TCNT 0x8D
3
#define PRESCALER 0x03

sein. Der Fehler ist dann 0.174%

Ich benutze dazu diesen Rechner:

http://www.b9.com/elect/avr/kavrcalc/index.html

welcher auch unter Linux mit Wine läuft.

Zur Not könnte man auch die Tick Zeit mal mit einem sleep vergleichen...

Viele Grüße

Daniel

von little man (Gast)


Lesenswert?

Hey,

super Rechner. Wusste garnicht, dass es sowas gibt. Hab es mir immer 
selbst alles ausgerechnet.

Bis dann!

von little man (Gast)


Lesenswert?

Hey,

hab den Test noch mal mit den genaueren Werten durchgeführt. Fehlmessung 
von ca. 1%. Also, danke noch mal für den Tipp!

Noch ne Frage!
Welche Karten (SD und MMC) akzeptieren MMC_MULTI_BLOCK? Hab bisher noch 
keine gefunden.

Bis dann!

von Daniel R. (zerrome)


Lesenswert?

Hm, seltsam.
Ich hab nur ein paar total alte Karten bei denen das nicht geht.
Neuere SD sollten das auf jeden Fall haben.

Viele Grüße

Daniel

von Peter (Gast)


Angehängte Dateien:

Lesenswert?

Hi,
ich benutze auch die Lib hier, hab aber ein Problem. Ich schreib alle 5 
Minuten auf die Karte alle 5 Sekunden 2 Werte. Nach ungefaehr 2 Stunden 
bricht das schreiben ab, weil entweder der Schreibvorgang hängenbleibt 
oder die er beim öffnen der Datei hängen bleibt. Vielleicht einer eine 
Idee, woran das liegen könnte? Die Schaltung wird über einen Lf33cf mit 
3,3 v versorgt, also auch stabil. Hab mal die main angehangen, ist im 
Grunde nur eine Erweiterung des beigefügten Beispiels im svn. Ach so µC 
ist ein Atmeg644p.

Grüße Peter

von Matze N. (hupe123)


Lesenswert?

*abo

von Daniel R. (zerrome)


Lesenswert?

Hallo,
sehe ich das richtig, dass der Atmeg644p 4k Ram hat? Weil eigentlich 
würde ich auf Ram Probleme tippen.
Läuft das Programm ohne schreiben auf die SD Karte normal durch?
Versuch mal die Datei einfach geöffnet zu lassen.
Du legst nicht alle 5 Minuten eine neue Datei an oder?

Hab grad nicht die Zeit mir das Programm im Detail anzuschauen, mach ich 
aber am Wochenende.

Viele Grüße

Daniel

von Peter (Gast)


Lesenswert?

Hi,
danke für die Antwort, jo der Atmega644p hat 4kb Ram, nur öffnen geht 
über viele Stunden, hab es dann irgendwann einfach abgebrochen. Nein ich 
öffne nur die existierende Datei immer wieder, schreib rein und 
schliesse sie.
Ich teste jetzt erstmal ohne die Datei immer zu öffnen, ob das schreiben 
dann über einen längeren Zeitraum funktioniert.

Mfg
Peter

von Daniel R. (zerrome)


Lesenswert?

Hallo,
also so nochmal auf die schnelle...
Bist Du Dir sicher, dass nur wirkliche Strings mit ffwrites geschrieben 
werden? Wenn da irgendwo das '\0' fehlt geht das schief.

Grüße

Daniel

von Tobias M. (obi)


Lesenswert?

Hi!

Ich möchte mir einen Datenlogger mit SD bauen.
Gibt es da irgendwelche Beschränkungen?
Also wie groß darf die SD- Karte maximal sein und was für einen µC 
braucht man mindestens?

Danke und Gruß
Tobias

von holger (Gast)


Lesenswert?

>Ich möchte mir einen Datenlogger mit SD bauen.

Wofür?

>Gibt es da irgendwelche Beschränkungen?

Ja. 4GB pro Datei maximal bei FAT32.
Schreibzeiten beschissen wegen sporadischen Aussetzern von
bis zu 500ms. Es sei denn du hast einen Arsch voll RAM.

>Also wie groß darf die SD- Karte maximal sein und was für einen µC
>braucht man mindestens?

FAT32 kann ein paar Terabyte.
ATmega mit mindestens 2kB Ram.

von obi (Gast)


Lesenswert?

>>Ich möchte mir einen Datenlogger mit SD bauen.
>
> Wofür?

Für eine Wetterstation

>>Gibt es da irgendwelche Beschränkungen?
>
> Ja. 4GB pro Datei maximal bei FAT32.
> Schreibzeiten beschissen wegen sporadischen Aussetzern von
> bis zu 500ms. Es sei denn du hast einen Arsch voll RAM.
>
>>Also wie groß darf die SD- Karte maximal sein und was für einen µC
>>braucht man mindestens?
>
> FAT32 kann ein paar Terabyte.
> ATmega mit mindestens 2kB Ram.

Also wenn ich eine 4GB SD- Karte nehme und nen atmega644 mit 4k sram 
müsste das kein problem sein oder?

von Peter (Gast)


Lesenswert?

Hi, ich nochmal,
also die Strings die mittels ffwrite geschrieben werden, sind alle mit 
\0 terminiert. Hab es jetzt ohne ständiges öffnen uns schliessen 
probiert. Brachte auch keinen Erfolg. Brauch nach circa 2h bei einem 
ffwrites ab.
Vielleicht haste noch eine Idee woran es liegen koennte. Danke schon 
mal.

Peter

von Daniel R. (zerrome)


Lesenswert?

Hallo.

@obi (Gast)
Nee das sollte kein Problem sein.

@Peter (Gast)
Hm, Du versuchst das nicht Batterie betrieben oder?
Beim schreiben zieht so eine Karte mal gut strom...

Über welche Datenmenge sprechen wir denn da bei den 2 Stunden?

Viele Grüße

Daniel

von Daniel R. (zerrome)


Lesenswert?

Hallo.

@Peter (Gast)
Bist Du da noch dran an dem Problem?

Nur der Vollständigkeit halber, wenn man viel Strom aus einer schwächer 
werdenden Batterie zieht, bricht die Spannung ein -> Kontroller Reset...

von Peter (Gast)


Lesenswert?

Hi,
im Grunde schon, habs erstmal nen bisschen weiter nach hinten geschoben, 
genug andere Arbeit. Ne ich betreib es mit einem Netzteil, und nen 
lf33cv, der sollte eigentlich genug Strom liefern. Ich glaub 
mittlerweile auch nicht mehr das es an der Lib liegt, sondern eher an 
der Karte, SanDisk Extreme III, hab nur leider keine andere zur Hand.

Gruesse
Peter

von Paul P. (pommespaule)


Angehängte Dateien:

Lesenswert?

Guten Abend,
erstmal: Absolut genial was hier für eine Lib entstanden ist. Da muss 
man schon mal den Hut ziehen !

Ich hab allerdings noch ein Problem mit dem Schreiben. Lesen 
funktioniert einwandfrei.
Wenn ich ein einzelnes Byte schreiben will (die Datei ist vorhanden und 
in ihr war vorher auch nur ein Byte):
1
if(TRUE == fat_loadFatData()){
2
  unsigned char file_name_offset[]="OFFS    KOM";
3
  if(MMC_FILE_EXISTS == ffopen(file_name_offset)){
4
    ffwrite(0x99);
5
    ffwrite(0x99);
6
    ffclose();
7
    }
8
  }
muss ich, wie ihr seht, den Befehl dazu zwei Mal geben. Wenn das zweite 
ffwrite auskommentiert ist, tut sich in der Datei gar nichts.

Das Anhängen an die Datei per vorgeschobenem
1
 ffseek(file.length)
funktioniert weder mit einem noch mit zwei Befehlen.

Meine Config habe ich mal angehängt.
Bin über jeden Hinweis dankbar.
Grüße Paul

von Uwe B. (boerge) Benutzerseite


Lesenswert?

MoinMoin,

es wäre gut, wenn du mal einige Konstellationen von Defines in config.h 
ausprobierst! Ich wollte gerade deine Lib mit "readonly" übersetzen und 
bekam einige Fehler um die Ohren gehauen. Z.B., wenn man

#define MMC_WRITE FALSE

setzt, kommt:

/home/x/work/x/sd_card/file.c:626: undefined reference to 
`fat_setClusterChain'
/home/x/work/x/sd_card/file.c:627: undefined reference to 
`fat_getFreeClustersInRow'

Grüße & Danke Uwe

von Uwe B. (boerge) Benutzerseite


Lesenswert?

...Zusatz:

wenn man

#define MMC_LFN_SUPPORT  FALSE

setzt, stürzt das Beispielprogramm beim Schreiben der Testdatei 
reproduzierbar ab...

Du solltest wirklich mal dringenst ein Codereview machen!

Grüße Uwe

von Daniel R. (zerrome)


Lesenswert?

Hallo,
bin gerade etwas eng mit der Zeit die ich fürs Hobby zur Verfügung habe.

Das mit dem "readonly" Fehler ist reingekommen, weil ich da die defines 
umgebaut hatte.

#define MMC_LFN_SUPPORT  FALSE
Das schau ich mir morgen oder die Tage mal an. Glaub ich so nicht 
richtig. Läuft bei mir nämlich in anderen Projekten problemlos.

Nur bei schnellen Prozessoren kann es Probleme mit den low level mmc 
Funktionen geben hab ich bemerkt. Aber das sind dann auch keine AVR 
mehr...

Grüße

Daniel

von Uwe B. (boerge) Benutzerseite


Lesenswert?

MoinMoin,

meine Testumgebung ist ein Mega168 mit 16MHz getaktet, also eigentlich 
deine Default-Konfiguration...

Daniel R. schrieb:
> #define MMC_LFN_SUPPORT  FALSE
> Das schau ich mir morgen oder die Tage mal an. Glaub ich so nicht
> richtig. Läuft bei mir nämlich in anderen Projekten problemlos.
>
Das Fehlerbild sieht wie folgt aus: es kommen genau zwei Zeilen des 
Dateiinhaltes, auch wenn mehr drin steht.

Grüße Uwe

PS.: für mich wäre es wichtig, wenn die "readonly"-Geschichte 
funktioniert. Ich könnte auch selbst am Code rummachen, aber habe keine 
Berechtigung, das Zeugs wieder ins SVN zurück zu laden... Deshalb würde 
ich es gerne dir überlassen!

von Uwe B. (boerge) Benutzerseite


Lesenswert?

MoinMoin,

ein weiterer Fehler:

file.c --> ffls() --> lsRowsOfClust()

Ein Dateiname ist mindestens 11 Zeichen lang. Du deklarierst temp als 
Array mit 11 Byte und schreibst an die 11.Stelle eine \0, als 
Stringende. Damit geht das letzte Zeichen des Dateinamen verloren...

Grüße Uwe

PS.: sorry, dass ich so penetrant bin. Ich wollte eigentlich deine Lib 
zum Einlesen von Basic-Programmen 
(http://www.mikrocontroller.net/articles/AVR_BASIC) von einer SD-Karte 
benutzen, stolpere aber derzeit leider über die Fehler in der Lib.

von Uwe B. (boerge) Benutzerseite


Lesenswert?

MoinMoin,

...siehe 
Beitrag "Re: Basic-Interpreter auf einem AVR"

Grüße Uwe

PS.: eine Funktion ffeof() wäre auch ganz nett...

PPS.: aber auch Lob für deine Lib, ich bin trotz einige Ungereimtheiten 
relativ schnell zum Ziel gekommen!

von Sven S. (schwerminator)


Lesenswert?

Tach auch.

Zuerst einmal: Eine super Bibliothek, die auf Anhieb funktioniert hat. 
Top!

Allerdings bin ich nun auf ein Problem gestoßen: Wenn ich eine Datei 
(zum Lesen) öffne und sie von Anfang bis Ende mit ffread() auslese, ist 
es mir danach nicht mehr möglich eine neue Datei zu öffnen. Egal ob ich 
die datei schließe oder nicht. Waron könnte das liegen?

Gruß Sven

von Daniel R. (zerrome)


Lesenswert?

Hallo,
da müsstest Du mal den Code zeigen. Kann ich so nicht viel zu sagen.



Grüße

Daniel

von Sven S. (schwerminator)


Lesenswert?

Hier kommt er:
1
unsigned char file_name[6]=" .mp3";
2
  unsigned char file_handle;
3
  for(uint8_t file_no=0; file_no<10; file_no++){
4
    file_name[0] = file_no + '0';
5
  
6
    printf("loop #%u, trying to open %s\n", file_no, file_name);
7
  
8
    file_handle = ffopen(file_name);
9
    if(MMC_FILE_EXISTS != file_handle)
10
      printf("Error opening file: %s (%u)\n", file_name, file_handle);
11
    else{
12
      printf("%s opened. Size: %lu Bytes\n", file_name, file.length);
13
14
      for(uint32_t b=0; b<file.length/512+1; b++) {
15
        // Regler per UART stellen
16
        input_1 = uart_getc();
17
        input_2 = uart_getc();
18
        if ( !(input_1 & UART_NO_DATA)  && !(input_2 & UART_NO_DATA) ){
19
          switch(input_1){
20
            case 1: sta015_set_atten(input_2); break;
21
            case 2: sta015_set_bass((int8_t)input_2); break;
22
            case 3: sta015_set_treble((int8_t)input_2); break;
23
          }      
24
        }
25
      
26
        // alle 128kB nenn bissel Info lesen
27
        if((b & (0x000000FF)) == 0xFF){
28
          printf("%u Kbit/s ", sta015_read_reg(STA015_REG_AVERAGE_BITRATE)<<1);
29
          printf("Head: 0x%02X%02X%02X ", sta015_read_reg(STA015_REG_HEAD_H), sta015_read_reg(STA015_REG_HEAD_M), sta015_read_reg(STA015_REG_HEAD_L));
30
          printf("Error: 0x%02X ", sta015_read_reg(STA015_REG_ERROR_CODE)&0x3F);
31
          //printf("Ancillary Data bits: 0x%02X%02X ", sta015_read_reg(STA015_REG_ANCCOUNT_H), sta015_read_reg(STA015_REG_ANCCOUNT_L));
32
          //printf("Ancillary Data 1: 0x%02X ", sta015_read_reg(STA015_REG_ANC_DATA_1));
33
          uart_putc('\n');
34
        }
35
    
36
        // Noch zu lesende Bytes ermitteln
37
        int16_t max = 512;
38
        if(b==file.length/512)
39
          max = file.length%512;
40
        
41
        // 512 Bytes von der SD-Karte lesen
42
        SPCR &= ~(1<<CPHA);
43
        for(uint16_t byte=0; byte<max; byte++)
44
          buffer[byte] = ffread();
45
        SPCR |= (1<<CPHA);
46
    
47
    
48
        // BIT_EN auf High
49
        SPI_CS_STA_PORT |= (1<<SPI_CS_STA);
50
    
51
        int16_t i = 0;
52
        // Block an den Decoder senden
53
        while(i < max){
54
          // Auf Data Request warten
55
          while(!(STA015_DATAREQ_PIN & (1<<STA015_DATAREQ)));
56
      
57
          // So lange wie Data Request an ist, Daten senden
58
          while((STA015_DATAREQ_PIN & (1<<STA015_DATAREQ)) && i < max){
59
            // Zeichen an den Decoder senden
60
            SPDR = buffer[i++]; num_bytes++;
61
            // auf SPI Übertragung warten
62
            while(!(SPSR & (1<<SPIF)));
63
          }
64
        }
65
    
66
        // BIT_EN auf LOW
67
        SPI_CS_STA_PORT &= ~(1<<SPI_CS_STA);
68
      }
69
    
70
      ffclose();
71
      printf("Track over\n");
72
    }
73
  }
74
  printf("%lu Bytes gelesen/uebertragen\n", num_bytes);
75
  printf("Fertig!\n");

von Daniel R. (zerrome)


Lesenswert?

Hallo,
wie äußert sich das denn. Bleibt er beim öffnen hängen oder wie?
Versuch mal testweise die Karte vor dem erneuten öffnen neu zu 
initialisieren. Wie sieht die config.h aus und die Initialisierung der 
FAT/Karte?

Viele Grüße

Daniel

von Sven S. (schwerminator)


Lesenswert?

Moin Daniel. Wenn ich die SD-Karte und die FAT neu initialisiere, 
funktionierts. Er hatte zuvor gemeldet, die Datei würde nicht 
existieren.

An der Initialisierung der SD habe ich nichts geschraubt und so von dir 
übernommen. Hier meine config.h:
1
  //#####################################################################################
2
  // BOOL DEFINITIONEN
3
4
  #define TRUE   1
5
  #define FALSE   0
6
7
  //#####################################################################################
8
  // FLAGS
9
10
  // flags fuer ffopen (sind die rueckgabewerte von ffopen, auf diese wird geprueft..)
11
  #define MMC_FILE_NEW       0  // datei existierte nicht, wurde gerade angelegt !
12
  #define MMC_FILE_EXISTS     1  // datei existiert, es kann gelesen werden !
13
  #define MMC_FILE_NOT_EXISTS     2  // datei existiert nicht, wird nur bei read-only zurueckgegeben, wenn die datei nicht gefunden wurde !
14
15
16
  //#####################################################################################
17
  // WICHTIGE SCHALTER
18
19
  // schalter die den funktionsumfang aendern bzw, den funktionsumfang einiger funktionen :)
20
  #define MMC_WRITE           FALSE  // TRUE, dann mit write unterstuetzung, wenn FALSE dann read only !
21
  #define MMC_OVER_WRITE       FALSE  // TRUE und MMC_WRITE TRUE, dann kann ffwrite dateien überschreiben, wenn FALSE dann nur normales schreiben. um an eine datei anzuhaengen ist MMC_OVER_WRITE TRUE nicht noetig!
22
  #define MMC_MULTI_BLOCK     FALSE  // TRUE und MMC_OVER_WRITE FALSE, dann werden multiblock schreib/lese funktionen benutzt. ist schneller, wird aber möglicherweise nicht von allen karten unterstützt. wenn FALSE ist normale operation
23
  #define MMC_SDHC_SUPPORT    FALSE  // TRUE, dann mit sdhc unterstuetzung, wenn FALSE, dann nur mmc/sd karten. siehe : http://de.wikipedia.org/wiki/SD_Memory_Card#SDHC_.28SD_2.0.29
24
  #define MMC_ENDIANNESS_LITTLE    TRUE  // TRUE, dann ist der code auf littleendian ausgelegt. AVR ist littleendian. code ist auf littleendian optimiert!! siehe: http://de.wikipedia.org/wiki/Endianness
25
  #define MMC_LFN_SUPPORT      TRUE  // TRUE, dann mit unterstuetzung fuer lange dateinamen. kostet wenn read und write benutzt wird um die 800 bytes flash...
26
  #define MMC_RM_FILES_ONLY    TRUE  // TRUE ,MMC_WRITE TRUE und MMC_RM TRUE, dann wird die funktion ffrm so mit kompiliert, dass sie nur dateien loeschen kann. wenn FALSE und MMC_WRITE TRUE, dann kann die funktion dateien und ordner rekursiv loeschen !
27
28
  // schalter die explizit funktionen mit kompilieren oder nicht!
29
  #define MMC_TIME_STAMP       FALSE   // TRUE, dann werden die funktionen fat_getTime und fat_getFreeBytes mit kompiliert. siehe auch abschnitt: ZEIT FUNKTIONEN, weiter unten
30
  #define MMC_RM               FALSE  // TRUE und MMC_WRITE TRUE, dann wird die funktion ffrm mit kompiliert.
31
  #define MMC_SEEK            TRUE  // TRUE,dann wird die funktion ffseek mit kompiliert. mit dieser funktion kann man in einer geoeffneten datei vor und zurueck spulen. nur in kombination mit MMC_OVER_WRITE TRUE kann in einer datei ueberschrieben werden.
32
  #define MMC_MKDIR            FALSE  // TRUE und MMC_WRITE TRUE, dann wird die funktion ffmkdir mit kompiliert. mit dieser funktion kann man ordner anlegen.
33
  #define MMC_GET_FREE_BYTES  TRUE  // TRUE, dann wird die funkton fat_getFreeBytes mit kompiliert. mit dieser funktion kann der freie platzt auf der karte ermittelt werden
34
  #define MMC_LS              TRUE  // TRUE, dann wird die funktion ffls mit kompiliert. mit dieser funkion kann man die dateien auf der karte anzeigen lassen
35
  #define MMC_CD              TRUE  // TRUE, dann werden die funktionen ffcd und ffcdLower mit kompiliert. mit diesen funktionen kann man in ein verzeichnis wechseln oder aus einem verzeichnis ein verzeichnis hoeher wechseln.
36
  #define MMC_FILE_EXSISTS    TRUE  // TRUE, dann wird die funktion ffileExsists mit kompiliert. mit dieser funktion kann geprueft werden, ob es die datei im aktuellen verzeinis gibt !
37
  #define MMC_WRITE_STRING    TRUE  // TRUE und MMC_WRITE TRUE, dann wird die funktion ffwrites mit kompiliert. mit dieser funktion koennen strings auf die karte geschrieben werden.
38
39
  // vorsicht, da die variable die die sektoren zählt ein short ist (MMC_MAX_CLUSTERS_IN_ROW*fat.secPerClust) !!
40
  #define MMC_MAX_CLUSTERS_IN_ROW 256   // gibt an wie viele cluster am stück ohne fat-lookup geschrieben bzw gelesen werden können, wenn die fat nicht fragmentiert ist !
41
42
  // wenn "#define INLINE inline" dann werden die statischen funktionen inline kompiliert. macht code groeßer, aber auch schneller!
43
  //#define INLINE inline
44
  #define INLINE
45
46
47
  //#####################################################################################
48
  // SPI EINSTELLUNGEN
49
50
  // wenn MAX_SPEED FALSE dann wird die SPI bus geschwindigkeit nicht hoch gesetzt. ist zum testen von hardware die nicht richtig läuft
51
  #define MMC_MAX_SPEED     TRUE
52
  #define MMC_STATUS_INFO   FALSE
53
54
  // software spi? wenn TRUE muessen in der mmc.h noch die pins eingestellt werden über die die spi kommunikation laufen soll
55
  // es werden nur pins an einem port unterstuetzt !
56
  #define MMC_SOFT_SPI   FALSE

Schönen Gruß!

von docean (Gast)


Angehängte Dateien:

Lesenswert?

Paul P. schrieb:
> Das Anhängen an die Datei per vorgeschobenem ffseek(file.length) funktioniert 
weder mit einem noch mit zwei Befehlen.

dito bei mir!!!

von docean (Gast)


Lesenswert?

Version 0.5.9 tut!

von Sven S. (schwerminator)


Lesenswert?

Hast du eine Idee, woran mein Problem liegen könnte, Daniel?


Gruß Sven

von Daniel R. (zerrome)


Lesenswert?

Hallo.

Leider habe ich momentan keine Zeit wegen dem blöden Weihnachten.
Werde aber kommende Woche dazu kommen mir das alles anzuschauen und die 
Probleme zu beheben.

Viele Grüße

Daniel

von Paul P. (pommespaule)


Lesenswert?

docean schrieb:
> Version 0.5.9 tut!

Interessant, ich habe aber in der zwischenzeit schon einen Workaround 
gefunden. Mit der Funktion ffwrites() läuft es weil fat.bufferDirty = 
TRUE gesetzt wird. Als habe ich mir eine kleine Funktion hingepfuscht 
die das auch nach dem normalen ffwrite() erledigt. Aber mir schwant es 
schon, so elegant ist das nicht ;)
Vielleicht hilft es ja bei der Fehlersuche. Schönen Feiertag noch

von Kurt B. (kurt)


Angehängte Dateien:

Lesenswert?

Hallo Daniel,
mir ist etwas merkwürdiges aufgefallen:

Ich schreibe zuerst 10kB in die Datei. Dann schließe ich sie, öffne sie 
erneut und hänge nochmal 10kB hintendran.

Win XP zeigt dann auch den richtigen Inhalt mit 20kB an. Wenn ich chkdsk 
laufen lasse werden aber Fehler korrigiert und die Datei hat danach 
24kB!

Mega32 @ 8MHz, 5V

Guten Rutsch!

Mfg,
Kurt

von Michael R. (Gast)


Lesenswert?

Hallo Daniel,
zunächst vielen Dank für die tolle Arbeit.
Ich habe eine ganzen Tag gebraucht, um meine alten 16MB-SD-Karten zum 
Laufen zu bringen.
Problem war offensichtlich, dass Windows 16MB-Karten nur mit FAT12 
formatiert und diese FAT12 dann beim Schreiben durch den AVR zerstört 
wird.

Wenn man in der Console dagegen "format x: /a:2048" verwendet, wird auch 
die 16MB-Karte in FAT16 formatiert und nun funktioniert alles. Ein 
Hinweis darauf in der Doku wäre nicht schlecht.
Oder vielleicht beim Initialisieren prüfen, ob da auf der Karte 
überhaupt eine nutzbare FAT16 oder FAT32 drauf ist, bevor man da was 
kaputtschreibt.

Eine andere Frage:
Vermutlich gibt es keine Möglichkeit, die 512Bytes RAM für den 
Sektorbuffer irgendwie zu reduzieren?
Mein ATMEGA16 ist da zusammen mit anderen Programmteilen schon extrem 
voll und ich hab da ein bissel Angst vor einem Stack Overflow, bei dem 
ich dann ewig den Bug suche.

Michael

von Barny (Gast)


Lesenswert?

Michael R. schrieb:
> Vermutlich gibt es keine Möglichkeit, die 512Bytes RAM für den
> Sektorbuffer irgendwie zu reduzieren?
Bei Flash-Speichern müssen immer 512Byte auf einmal geschrieben werden.
Wenn man alles auf einen Rutsch schreiben will, braucht man eben diesen 
Speicher.
Du hast jetzt 2 Möglichkeiten.
Entweder du optimierst den Speicherverbrauch, oder du steigst auf einen 
ATmega32 um.

von Michael R. (Gast)


Lesenswert?

Hallo Daniel,
Ich habe hier auch noch ein seltsames Problem bezüglich Anhängen.
Wenn der AVR frisch startet und an eine bestehende Datei anhängen soll, 
dann geht das schief. file.length gibt bei jedem neuen Öffnungsversuch 
immer wieder den gleichen Wert zurück, obwohl ich zwischendurch bei 
geöffneter Datei mit ffwrites was angehängt habe.
Also folgende Reihenfolge:
-Init-CARD/FAT
-ffopen
-ffseek(file.length) (falls MMC_FILE_EXISTS zurückkommt)
-ffwrites
-ffclose
-Init-CARD/FAT (Ich mach das jedes Mal, zur Sicherheit)
-ffopen
-ffseek(file.length)
-ffclose

Beim zweiten ffseek wird genau das gleich zurückgeliefert, wie beim 
ersten ffseek. Die Datei wird einfach nicht größer

Wenn die Datei dagegen frisch angelegt wird, scheint das Verlängern 
beliebig häufig zu klappen, bis ich den AVR neu starte, dann geht es 
wieder nicht.
Also eine bereits vor AVR-Boot bestehende Datei wird nicht mehr 
verlängert, eine gerade selbst angelegte Datei lässt sich immer 
verlängern.

Die 16MB-Karte Karte ist so formatiert(chkdsk-Ausgabe):
  14,1 MB Speicherplatz auf dem Datenträger insgesamt.
  14,1 MB sind verfügbar.

    2.048 Bytes in jeder Zuordnungseinheit
    7.241 Zuordnungseinheiten auf dem Datenträger verfügbar

       16 Bits in jedem FAT-Datensatz.

Irgendwie sieht das so aus, als wird irgendwas nicht richtig 
initialisiert.

  Michael

von Michael R. (Gast)


Lesenswert?

Zu dem Anhängen-Problem:
Ich habe mal ein bisschen weiter gewühlt:
Beim Anhängen werden die Daten richtig auf die Karte geschrieben und 
sind mit einem Hex-Editor auffindbar. Ändert man mit dem Hex-Editor die 
Dateigröße, dann werden die geschriebenen Daten auch für das normale 
Windows Notepad sichtbar.
Beim Schließen der Datei wird scheinbar der FAT-Eintrag nicht richtig 
aktualisiert. Mindestens die Dateigröße wird falsch geschrieben.
Ich habe zwar die Funktionsaufrufe beim flush bis runter zum

mmc_write_sector( fat.currentSectorNr,fat.sector );

nachvollzogen, konnte aber nicht rausfinden, warum die Dateigröße nicht 
oder nicht richtig geschrieben wird. (Habe keinen Debugger, ist sehr 
mühsam).

Michael

von Michael R. (Gast)


Lesenswert?

Soo,
noch ein Stück weiter:

Wenn der AVR die Datei in der aktuellen Sitzung nicht selbst erstellt 
hat,
dann enthält "fat.currentSectorNr" beim Aufruf von "fat_loadSector "in 
der "fflushFileData" immer 0.

fflushFileData:
1
// dafuer sorgen, dass der sektor mit dem geaenderten dateieintrag geschrieben wird, beim neuladen. datensektor der datei neuladen, falls noch weitere bytes geschrieben werden.
2
  fat.bufferDirty = TRUE;
3
  fat_loadSector( save_currentSectorNr );
Das führt dazu, dass "fat_loadSector" versucht, die aktuellen Daten nach 
Sektor 0 zu speichern:
1
  mmc_write_sector( fat.currentSectorNr,fat.sector );  // schreiben von sektor puffer

Glücklicherweise geht das wohl irgendwie schief und dem Bootsektor 
passiert dadurch offenbar nichts.
Warum "fat.currentSectorNr" nicht die Sektornummer des FAT-Eintrags hat, 
kann ich aber nicht mehr nachvollziehen, das wird mir dann zu 
unübersichtlich.

Michael

von Buzzwang (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

bei meiner SanDisk SD 2GB 2 tut es leider nicht.

Genaueres:
Bei meiner alten Karte(SanDisk Extreme III) hat es noch getan. Leider 
ist diese abgeraucht. Ich habe mir dann die oben gesagte gekauft. Init 
läuft durch. Jedoch beim Lesen des 1. Sector gibt es dann einen Zonk.
Unter Windows tut die Karte (FAT32).Im Anhang ist ein Log.
Ich werde mal sehe ob ich noch was rausfinde. Leider habe ich keine 2 
Karte zum gegentesten.

von Gerd G. (elektrikser)


Lesenswert?

Teste gerade die Lib mit verschiedenen Karten.
Bis jetzt funktionieren:
- Sandisk Sd-Card 2 GB
- Kingston SD-Card 256 MB
- Hama SD-Card 256 MB
- Sandisk Mikro-SD 2GB
- Sandisk Mobile Ultra Micro-SDHC 4GB

Mit Verzeichnisse anlegen habe ich noch nichts gemacht. Mir ging es erst 
einmal um das Speichern und Lesen von Daten.

Gruß Gerd

von Buzzwang (Gast)


Lesenswert?

habe gefunden woran es liegt. Ist ein Problem in "mmc_read_sector"

Warte auf 0xFE tut nicht.

Wenn man es ändert auf z.B.
1
   if( 0 != mmc_write_command(cmd))  
2
   {
3
      return FALSE;
4
   }
5
6
   a = 0;
7
   do
8
   {
9
    //Wartet auf Start Byte von der MMC/SD-Karte (0xFE/Start Byte)
10
    a++;
11
    if (a == 255) return FALSE;
12
   }
13
   while (mmc_read_byte() != 0xFE);

dann tut es.

von ka-long (Gast)


Lesenswert?

Moin,

Meine MMC/SD Ansteuerung verhält sich sehr komisch...

Mit einem AtMega16/8MHz hat es mit einer 4GB/SDHC plötzlich funktioniert 
(ein Datenloggen über zwei Stunden ohne Probleme), nachdem ich den LFS 
eingeschaltet hatte...

Wegen zu wenig Speicher hab ich den ATMega16 gegen den pinkompatiblen 
Atmega32 getauscht. Leider habe ich zwischenduch den Code mal etwas (was 
auch immer) modifiziert...

Nach drei Abenden werd ich wohl jetzt frustriert aufgeben:

* mmc_init und load_fat funktionieren

Öffne ich ne Datei in meinem Code mit ffopen ohne was anderes zu tun, 
zeigt mein PC die Datei mit 0 Byte an, gut so.

Öffne ich die Datei und schließe sie direkt wieder mit ffclose, dann 
gibt es keine Datei, aber der PC kann die Karte noch lesen.

Öffne ich die Datei und schreibe ich etwas mit ffwrites wird die FAT 
zerschossen. Egal ob mit oder ohne ffclose.

SPI wird nicht hochgesetzt, ich versorge die Karte mit 3.3V aus einem 
Labornetzteil, der ATMega arbeitet allerdings auf 5V mit 
Spannungsteilern.

Ich hab mit nem Scope die Signale nachgemessen, alle da und für die 
Geschwindigkeit ausreichende Signalintegrität.

Eine andere Karte 2GB/SD läuft gar nicht.

Gruß ka-long

von Michael R. (Gast)


Lesenswert?

Hallo,
ka-long schrieb:
> Ich hab mit nem Scope die Signale nachgemessen, alle da und für die
> Geschwindigkeit ausreichende Signalintegrität.

insbesondere die Clock-Flanken bei SPI sind extrem kritisch. Wenn man 
keinen integrierten Pegelwandler verwenden möchte, kann man auch einen 
kapazitiven Spannungsteiler parallel zum normalen Spannungsteiler 
schalten. Folgende Kombinationen sollten funktionieren:

Oberer Kondensator | unterer Kondensator
22p                | 12p
27p                | 15p
33p                | 18p
39p                | 22p
47p                | 27p
56p                | 33p

Wenn ein Tastkopf dranhängt stimmt das Verhältnis wegen der 
Tastkopfkapazität aber nicht mehr. Man sieht also nicht mehr das 
gleiche, wie die Karte ohne Tastkopf sieht. Man muss sich auf die 
Mathematik verlassen.

Michael

von ka-long (Gast)


Lesenswert?

Hallo Michael,

Sind die Anstiegs- und Fallzeiten denn irgendwo definiert ?

Ich werd mal auf mmc-lib Sektor-Ebene Daten lesen und schreiben und 
schauen, ob es da zu Fehlern kommt oder obs in einer der höheren 
Schichten passiert.
So kann ich vielleicht die HW als Ursache ausschließen...


Gruß ka-long

von Michael R. (Gast)


Lesenswert?

ka-long schrieb:
> Sind die Anstiegs- und Fallzeiten denn irgendwo definiert ?

Wenn Du eine matschige CLK-Flanke hast und da noch Rauschen oder 
sonstige Spikes drauf sind, kann es passieren, dass der Empfänger 2 
Flanken kurz nacheinander sieht und dann auch 2 Bits einliest, obwohl 
nur eine Flanke gesendet wurde. In wie weit Doppelflanken unterdrückt 
werden, steht vielleicht im Datenblatt der Karte. Wenn die Karte aber 
z.B. 50MHz SPI unterstützt, dann muss sie Flanken im Abstand 10ns 
erkennen können. Wenn Deine Anstiegszeit aber z.B.100ns ist, dann hält 
sich der Pegel doch einige Zeit im kritischen Bereich auf und kann eine 
Doppelflanke auslösen, wenn Rauschen/Spikes überlagert ist.
Vernünftig entwickelte Clk-Eingänge haben Schmitt-Trigger-Eingänge und 
intelligente digitale Filter drin, die das Problem entschärfen. Aber 
gerade das ist wohl selten spezifiziert.

Die Flankensteilheit der Datenleitungen ist dagegen weniger kritisch, 
der Pegel muss nur zum Zeitpunkt der jeweiligen CLK-Flanke eindeutig 
high oder low sein.

Michael

von Andi S. (laserandi)


Lesenswert?

Hallo,
erstmal Danke für die gute Arbeit. Ich teste seit ein paar Tagen die 
Version 0.6.1 mit einem mega644. Leider läuft die main_simple.c nur dann 
durch, wenn ich den µC resete.
Schaltet man VCC aus und wieder ein bleibt das Programm in der 
fat_loadFatData(); hängen und zwar beim ersten Aufruf von 
loop_until_bit_is_set(SPSR,SPIF);" in der mmc_write_byte Funktion 
(mmc.c).
Was ich schon getestet habe:
- Verzögerung mit  _delay_ms --> ohne Erfolg
- Verschiedene 1 GB sd-Karten --> ohne Erfolg
- Brummspannung auf VCC < 20 mV (Die ganze Schaltung inkl. µC läuft mit 
3,3 V)
Ich glaube nicht, dass es ein Hardwareproblem ist.
Komisch ist, dass vor "fat_loadFatData();" noch die mmc_init(); 
problemlos aufgerufen wird, ohne das das Programm in mmc_write_byte fest 
hängt?!

Vielleicht könnt Ihr mir einen Tipp geben, was ich noch versuchen kann, 
damit die main_simple.c direkt durchläuft.
Danke.
Gruß
Andi

von Daniel R. (zerrome)


Lesenswert?

Hallo zusammen,
ich bin da gerade immer mal wenn ich etwas Zeit habe dran am arbeiten.

Ich habe jetzt einen stm32 mit jtag Debugger, damit arbeitet sich 
wesentlich leichter als mit einem avr und Debug Ausgaben über die 
Konsole :)

Was wohl auf jeden Fall geändert werden wird, sind die Delay schleifen 
in der mmc.c, die werden auf einen Timer umgestellt werden müssen.

Die Initialisierung der Karten wird auch geändert sowie der Ablauf von 
den schreibe und lese Funktionen. Also quasi der ganze Unterbau wird 
geändert. Zudem noch die Datei öffnen Funktion.

Bitte um etwas Geduld...habe bald Semesterferien, die letzten :) da wird 
das wohl spätestens was werden....

Viele Grüße

Daniel

von Michael R. (Gast)


Lesenswert?

Hallo Daniel,
wenn Du das Timing auf einen Timer umstellst, wird das Einbinden in 
verschiedene andere Projekte deutlich schwerer oder unmöglich. Ich habe 
Deine lib in einem Projekt drin, in dem keine Timer mehr verfügbar sind.

Super wäre es, erstmal eine stabile weitgehend bugfreie Version zu 
schaffen, denn derzeit ist das definitiv nicht der Fall.

Ansonsten finde ich Deine Arbeit echt super, eine Lib, die wenig 
Resourcen braucht und einfach einzubinden ist.

Michael

von Daniel R. (zerrome)


Lesenswert?

Hallo.

>wenn Du das Timing auf einen Timer umstellst

Genau da ist beispielsweise einer der Bugs. So eine Karte genehmigt sich 
schon mal bis zu 200 ms um Daten zu speichern oder um einen Block zu 
lesen. Da rasselt man dann einfach aus den warte Schleifen raus, 
zumindest so wie die momentan sind.

Ich hab mir das so vorgestellt, dass man einfach eine bestimmte Funktion 
im 10 ms Takt aufrufen muss.
Im Beispielcode würde ich dann ein Timer Beispiel machen, wie das dann 
letztendlich in einem eigenen Projekt umgesetzt wird muss dann jeder 
selber schauen...

Grüße

Daniel

von Michael R. (Gast)


Lesenswert?

Hallo Daniel,
ich meinte den z.B. den Bug, dass die FAT beim Anhängen nicht richtig 
geschrieben wird.
Ansonsten hat Dein Ansatz mit den Timern definitiv Vorteile, da der 
Controller in den Warteschleifen nicht blockiert wird.
Du baust also keine Timerfunktionen direkt in die Lib ein sondern 
erwartest ein Pollen Deiner Funktionen?

Michael

von recently (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich hätte mal eine Frage zur "Superfloppy"-Erkennung. Mit meiner frisch 
gekauften 2GB-SD-Karte lief das AVR-FAT-Paket auf meinem Pollin net-io 
mit SD-Addon zunächst tadellos. Diese SD-Karte hatte in Sektor 0 einen 
MBR mit Partitionstabelle. Nun habe ich die SD-Karte in meinem 
Windowsrechner neu mit FAT32 formattiert. Dadurch verschwand der MBR und 
die neue Partition beginnt nun ohne Umwege direkt in Sektor 0, die Karte 
hat also "Superfloppy"-Format. Wenn ich es richtig verstanden habe, 
untersucht die AVR-FAT-Software den Boot-Code der Partition auf die 
Zeichenkette "medi", die an der Stelle erwartet wird, wo sonst die 
Anfangsadresse der 1.Partition steht. Dies funktioniert bei mir nicht. 
Die Zeichenkette "medi" ist um 2 Bytes versetzt, wodurch die 
Superfloppy-Erkennung scheitert und alles weitere natürlich auch. Habe 
das Debugger-Listing angehängt, in dem der Versatz zu erkennen ist. Habe 
ich irgendetwas nicht richtig beachtet ?

Vielen Dank für Tipps
recently

von daniel (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
ich bin dazu gekommen mal ein wenig an der Lib zu arbeiten.
Als Anhang mal die frischen Dateien.

Es gibt einige Änderungen.

In der mmc.c ist aufgrund der Portierbarkeit ein eigener SPI Teil dazu 
gekommen. Zum anpassen an andere Plattformen müssen jetzt nur noch die 
Funktionen,

spi_init
spi_maxSpeed
spi_write_byte
spi_read_byte

und die defines,

#define MMC_CS_LOW     GPIO_ResetBits(GPIOA, GPIO_Pin_4)
#define MMC_CS_HIGH    GPIO_SetBits(GPIOA, GPIO_Pin_4)

angepasst werden.

Auch in der mmc.c geändert:
Die Initialisierung der SD/MMC Karten.
Die Bestimmung ob Superfloppy oder nicht.
Zeit gesteuerte delay Schleifen beim lesen/schreiben, wegen der Totzeit 
der Karten bei diesen Operationen.

Ganz wichtig! Es muss irgendwo eine globale Variable
1
 volatile unsigned char TimingDelay;
 geben, die in 10 ms Intervallen bis 0 runtergezählt wird!

In der file.c hat sich ffopen geändert.
Es wird jetzt nicht mehr einfach die Datei angelegt wenn sie noch nicht 
vorhanden war. Hat oft zu Verwirrung geführt.

ffopen(name,'r') öffnet die Datei falls vorhanden und gibt 
MMC_FILE_OPENED zurück. Oder aber MMC_NOTHING_DONE.

ffopen(name,'c') legt eine Datei an falls es die Datei noch nicht gibt 
und gibt MMC_FILE_CREATED zurück. Oder aber MMC_NOTHING_DONE wenn es die 
Datei schon gab...

In der fat.c hat sich das suchen nach Dateinamen geändert. Bei kurzen 
Dateinamen wird von PC Betriebssystemen manchmal nur ein SFN angelegt. 
Das ist jetzt in der Lib angepasst.


Es wird demnächst noch weiter gehen...

Grüße

Daniel

von Manfred (Gast)


Lesenswert?

Mit den neuen Modulen ist bei mir nichts mehr compilierbar ... schade, 
ob das jetzt wirklich ein Gewinn war ?

Gibt es denn dazu auch eine passendes "main_simple", das nach diesem 
Totalaustausch der Quellen noch läuft ? Das man es wenigstens mal 
ausprobieren kann ?

von recently (Gast)


Lesenswert?

Hallo Daniel,

vielen Dank für die neue Version. Die Superfloppy-Erkennung sieht gut 
aus. Gibt es denn auch eine AVR-Version ? Die Version im fix-zip-file 
scheint für STM32-Hardware ausgelegt ?

Viele Grüße
recently

von Daniel R. (zerrome)


Lesenswert?

Hallo,
es wird die Tage die AVR Version geben.
Jo, das ist für einen STM32 momentan.
Sollte jetzt keine finale Version sein.

Viele Grüße

Daniel

von daniel (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
jetzt sollten alle Fehler behoben sein.

Hier schonmal die STM32 Version. Bisher nur mit lfn Option getestet...
Die AVR Variante braucht noch etwas Zeit,
sollte aber auch relativ einfach aus der SMT32 Version zu portieren 
sein.

Viele Grüße

Daniel

von Michael R. (Gast)


Lesenswert?

Hallo,
ist der Datei Anhängen Bug gefixt?

Michael

von recently (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Daniel,

ich beschäftige mich gerade intensiv mit dem AVR-FAT-Code und habe eine 
Frage zum Element file.dir : Das Element wird in der Funktion 
fat_loadFatData einmal auf 0 gesetzt und dann an verschiedenen Stellen 
der Software auf 0 geprüft ... was ist die Bedeutung dieses Elements ?

von recently (Gast)


Lesenswert?

... meinte natürlich das Element "fat.dir"

von Daniel R. (zerrome)


Lesenswert?

Hallo,
da wird der 1. Cluster des aktuellen Verzeichnisses gespeichert. Damit 
man weiß in welchem Ordner man sich befindet.
Wird nur durch ffcd() und ffcdLower() geändert. Mit ffcd() wechselt man 
in ein Verzeichnis und mit ffcdLower() geht man ein Verzeichnis höher 
(auch als "cd.." bekannt).

Viele Grüße

Daniel


PS: Die AVR Version ist soweit. Bin nur noch ausgiebig am testen.

von recently (Gast)


Lesenswert?

danke für die schnelle Antwort ...

Viele Grüße
recently

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,
hier jetzt mal die fertigen Sachen.

Es wäre super, wenn ein paar Leute mittesten könnten.

Es gab eigentlich nur einen Bug, den ich selber eingebaut hatte von 
0.5.9 auf 0.6.1, dummerweise...

Der ist jetzt weg und es gibt neue Features...

Viele Grüße

Daniel

von recently (Gast)


Lesenswert?

Hallo Daniel,

mit meinem ATMega32 (der NetIO von Pollin) mit 18.432 MHz bekomme ich 
Schwierigkeiten beim compilieren ... Die Taktfrequenz wird im Header 
nicht angeboten und weiterhin hat der Mega32 auch kein "TCCR0A" ...

Viele Grüße
recently

von Daniel R. (zerrome)


Lesenswert?

Hm, dann musst Du den Timer per Hand einstellen.
Die Timer ISR muss alle 10ms aufgerufen werden.
Für den mega32 werde ich das aber wohl auch noch einbauen...

Grüße

Daniel

von nicht Gast (Gast)


Lesenswert?

Hallo,
ich werde deine Version auch testen.
Ich wollte mal fragen warum du überall "unsigned char var[]" als 
Parameter nutzt.
Könnte man da nicht "char *var" nehmen dann muss man nicht immer rum 
casten wenn man Standard lib Funktionen nutzt.
Also statt:
extern unsigned char ffopen( unsigned char name[], unsigned char 
rw_flag);
ein:
int8_t ffopen(char *name, uint8_t rw_flag);

Vielen dank das du das hier veröffentlicht hast, wie gesagt soll nur ein 
Vorschlag sein.

von XMEGA (Gast)


Lesenswert?

Servus,


 Daniel R. schrieb:
> Es wäre super, wenn ein paar Leute mittesten könnten.

hab mich mal mit der neuen  Version beschäftigt.

Bis jetzt war ich begeistert- aber nun macht es doch erhebliche 
Probleme. Insbesondere mit einem neuen Prozessor.

Die Timer-Geschichte mag zwar funktionieren ist aber gegen der 
vorherigen Version komplizierter geworden.

Mit den #If, #else, #endif  verliert man total die Übersicht.

Trotz alledem bin ich über Deine Vorgängerversion froh, die funktioniert 
ohne Probleme auf allen Atmegas/Atxmegas.

Gruß XMEGA

von Daniel R. (zerrome)


Lesenswert?

Hallo,
bei der Timer Version ist das einzige komplizierte, dass es eine ISR 
geben muss die alle 10ms aufgerufen wird und in der
1
TimingDelay = (TimingDelay==0) ? 0 : TimingDelay-1;
seht.
Sonst hat sich alles nur zum Vorteil geändert.
Besonders bei sfn (short file names) ist es doch wesentlich bequemer
1
 unsigned char file [] = "test.txt";
zu schreiben als
1
 unsigned char file [] = "TEST    TXT";

Aber gut, zu dem Timer Punkt werde ich mir etwas überlegen. Vielleicht 
hat ja jemand eine Idee, wie man aus F_CPU und ein paar Assembler 
Befehlen auch so etwas hinbekommen kann wie gezieltes warten von maximal 
200 ms.

Wenn man eclipse als IDE benutze, kann man die #if die nicht benutzt 
werden ausblenden lassen, oder sie grau hinterlegen lassen, das ist sehr 
übersichtlich.

char * mag ich nicht als Standard Typ verwenden, weil das signed ist und 
somit im 2er Komplement. Das ist nicht so Ressourcen schonend...

Viele Grüße

Daniel

von nicht Gast (Gast)


Lesenswert?

Daniel R. schrieb:
> char * mag ich nicht als Standard Typ verwenden, weil das signed ist und
> somit im 2er Komplement. Das ist nicht so Ressourcen schonend...

Aha, ok wenn du meinst, für String Bearbeitung macht das zwar keinen 
unterschied aber nun ja...

Für den Timer währe es sinnvoll wenn man per define einstellen könnte 
alle wie viel ms die Zähler runtergezählt wird, so könnte man eine 
Bestehende Timer Funktion verwenden.
1
// in Header
2
#define COUNT_VALUE  15  // Value in ms
3
4
// irgendwo im Code
5
TimingDelay = 1000 /  COUNT_VALUE;
6
if(!TimingDelay)
7
  TimingDelay =1;
8
while(wait);

von Daniel R. (zerrome)


Lesenswert?

Den Code versteh ich nicht...

Wie ist das gemeint?

Man kann doch bestehende Timer einfach mitbenutzen... es muss halt nur 
TimingDelay im 10ms Takt um 1 runter gezählt werden, bis auf 0.
Um mehr muss man sich nicht kümmern.

von nicht Gast (Gast)


Lesenswert?

Daniel R. schrieb:
> es muss halt nur
> TimingDelay im 10ms Takt um 1 runter gezählt werden

Und das ist der Punkt. wenn deine Timer mit z.B. 15ms oder 5ms laufen 
kannst du sie nicht so einfach benutzen.
Bzw. musst du selber im Timer schauen das du z.B (5ms) nur jedes zweite 
mal dekrementierst oder (15ms) jedes zweite mal doppelt dekrementieren 
musst.

von nicht Gast (Gast)


Lesenswert?

Sorry hatte da noch einen kleinen Fehler im Code
1
// in Header
2
#define COUNT_VALUE  15  // Value in ms
3
4
// irgendwo in mmc.c
5
TimingDelay = 1000 /  COUNT_VALUE;
6
7
if(!TimingDelay)
8
  TimingDelay =1;
9
10
while(TimingDelay && funktionaufdiegewartetwird());

von Daniel R. (zerrome)


Lesenswert?

Ok, ich dachte ja nur, dass ich ein Beispiel der Benutzung gebe.

>..wenn deine Timer mit z.B. 15ms oder 5ms laufen
>kannst du sie nicht so einfach benutzen...

Wenn man das dann in ein Projekt einbaut, muss man sich genau um solche 
Dinge ja Gedanken machen und ändern.

Mit der Anweisung:
Decrementiere TimingDelay im 10ms Takt um 1, bis auf 0, sollte man ja 
klar kommen können.
Man kann aber auch einfach TimingDelay nach 200ms auf 0 setzten und gut 
ist. Die Idee ist halt, mindestens 200ms auf die Karten zu warten.

Ich Persönlich würde ja eine Lösung ganz ohne Timer auch besser finden, 
hab aber noch nicht die zündende Idee wie man das schön machen könnte.

von little_man (Gast)


Lesenswert?

Hallo,

Allgemeine Frage:
Funktioniert der Code mit MMCplus Karten?

Bekomme nämlich Transcend MMCplus Karten (1GB & 2 GB) nicht ans laufen!
Die Karte kann nicht initialisiert werden. Andere Karten funktionieren!

mfg

von Kurt B. (kurt)


Lesenswert?

Ich bekomme leider auch eine 2GB Verbatim SD-Card und eine 1GB von 
Platinum nicht zum laufen. Nur eine alte 1GB Noname funktioniert.

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ist MMCplus der Standard 3.0 ? Das sollte nämlich gehen.

Wobei ich mehrmals Probleme hatte ist, wenn der MISO Pin keinen Pullup 
hat. Das geht mit alten Karten meistens noch, aber mit neuen nicht mehr.

Den Initialisierungs Kram hab ich bei anderen abgeschaut, und nur noch 
mal mit den Specs verglichen...

>Man kann aber auch einfach TimingDelay
>nach 200ms auf 0 setzten..

Muss ich mir selber etwas widersprechen, ist nämlich einmal nach 200ms 
und beim Initialisieren der Karten 1000ms...

Viele Grüße

Daniel

von Kurt B. (kurt)


Lesenswert?

Leider funktioniert trotz MISO PullUP nur eine der 3 Karten. Mit der 
0.5.9C hatten die alle funktioniert.
Schade dass ich keine Zeit zur Fehlersuche habe.

Aber jetzt was positives: Die Performance scheint besser geworden zu 
sein. Statt 60kB/s sind es nun 80kB/s auf einem Mega32 mit 18,432Mhz.

Mfg,
Kurt

von Daniel R. (zerrome)


Lesenswert?

Hallo,

>..0.5.9 hatten die alle funktioniert..

das blöde ist das ich keine Karte habe mit der es nicht klappt, daher 
ist das Fehlersuchen nicht möglich.

80kB/s ist aber trotzdem sehr langsam. Benutzt Du software SPI?
Mit 18,432Mhz Quarz und hardware SPI müsste das eine sehr langsame Karte 
sein.

Ich hab hier SD Karten die mit 16Mhz 170kB/s machen. Auch welche mit 
über 200kB/s...

Alles schreibend, lesend noch schneller...

Außerdem ist an den schreib Routinen eigentlich nichts geändert.

Viele Grüße

Daniel

von Kurt B. (kurt)


Lesenswert?

Nein, ich nutze Hardware SPI.
Wahrscheinlich liegt die geringe Geschwindigkeit daran dass ich immer 
nur ein einzelnes Byte schreibe?

Falls sonst niemand Probleme mit den SD Cards hat, habe ich wohl einen 
Fehler eingebaut der so offensichtlich ist dass ich ihn immer übersehe. 
;-)

Mfg,
Kurt

von little_man (Gast)


Lesenswert?

Hallo!

>ist MMCplus der Standard 3.0 ?

Ich meine das ist der neue Standard 4.0. Kann mich aber auch täuschen!

mfg

von Daniel R. (zerrome)


Lesenswert?

@ Kurt Bohnen (kurt)

Also wenn Du normal mit ffwrite() schreibst, puffert die Lib eh 512 
Bytes zwischen. Da sollte das Problem nicht liegen.
Ach ja, wenn überschreiben an ist, ist das schreiben etwas langsamer...

@ little_man (Gast)

Ja stimmt, ist 4.x, wenn Du da eine Spezifikation findest, schau ich mir 
das mal an und setzt das dann um...


Viele Grüße

Daniel

von Sven S. (schwerminator)


Angehängte Dateien:

Lesenswert?

Das könnte helfen.

Gruß Sven

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ja das sieht auf den ersten blick schon mal sehr gut aus.


Danke :)

Viele Grüße

Daniel

von Kurt B. (kurt)


Lesenswert?

Daniel R. schrieb:
> Ich hab hier SD Karten die mit 16Mhz 170kB/s machen. Auch welche mit
> über 200kB/s...

Hallo Daniel,
kannst du ein paar Namen nennen?

Mfg,
Kurt

von Markus K. (Gast)


Lesenswert?

Hallo zusammen

Erstmal vielen Dank fuer die tolle Library. Bin ziemlich neu in der Welt 
von uC. Trotzdem habe ich es geschaft dank der Library auf die SD-Karte 
zu speichern. Das spricht wohl fuer sich. (super super Sache das)

Ein Problem habe ich aber noch.
1
 ffseek(file.length);
Dauert am Anfang ca. 5ms  30min. spaeter 28ms (Datei ist dann 2.85MB 
gross)

Habe weiter oben beim Eintrag vom 17.9.2010 gesehen das ffseek nicht 
durchgefuehrt werden muesste wenn File nicht geschlossen wird. 
Funktioniert bei mir aber leider nicht. (Auf dem SPI-Bus sind noch 
andere Teilnehmer. Sollte aber doch nichts ausmachen)

Um meine Frage kurz zu fassen: Wie kann ich die Zeit zum spulen 
verkuerzen?
(Sollte doch moeglich sein file.length zu merken aber wie?)

Vielen Dank

von Daniel R. (zerrome)


Lesenswert?

@ Kurt Bohnen (kurt)
Muss ich mal nachschauen, bin grad nicht zuhause.

@ Markus K. (Gast)
Schließt Du die Datei beim schreiben immer oder wieso das ffseek?
Du könntest alternativ ein fflush machen anstelle von schließen...

Zeig doch mal ein bisschen code


Viele Grüße

Daniel

von Markus K. (Gast)


Lesenswert?

Ja ich schliesse sie nach jedem anhaengen wieder. Hab auch mal versucht 
sie offen zu lassen doch dann stimmten die Eintraege nicht mehr. Ich 
haenge alle 200ms ein paar Daten an.(sollte so eine xml Datei entstehen)

Verstehe ich das richtig:
fflushFileData(); anstelle von ffclose();
und dann kein ffopen(filename); mehr oder?

Vielen Dank.

von Daniel R. (zerrome)


Lesenswert?

Ja genau.

>Hab auch mal versucht sie offen zu lassen
>doch dann stimmten die Eintraege nicht mehr.

Das müsstest Du mal genauer erklären, bzw zeigen, wie Du die lib 
benutzt.

Viele Grüße

von Markus K. (Gast)


Lesenswert?

Sorry war mein Fehler hab wohl irgendwo im Code vergessen ffclose oder 
ffopen auszukommentieren.

Nun funktioniert es mit dem geoeffnet halten der Datei.
Sorry

Nochmals Vielen Dank fuer deine tolle Library

von Daniel R. (zerrome)


Lesenswert?

Hi, kein Problem.
Viel Spaß noch :)

von Fabian B. (fabs)


Lesenswert?

Hallo Daniel.
 Danke erstmal für die Lib, grad die Fat Funktionen sind super und Fat32 
geht auch einwandfrei.

Ich habe aber immer wieder mit der Karteninitialisierung Probleme.
Kleine Karten < 1GB gingen vom Start weg aber die grossen, bei denen man 
im Init in den SDv2-Block läuft machten Probleme.
Ausserdem habe ich einige Karten gehabt, die nicht sofort auf CMD0 
reagiert haben. Und auch auf CMD16 reagieren manche nicht sofort. 
Hierfür habe ich jeweils eine Schleife eingefügt.

Ich habe die Init-Fuktion etwas angepasst:
1
unsigned char mmc_init (void){
2
3
  unsigned char cmd, ty, ocr[4];
4
  unsigned short n, j;
5
6
  spi_init();
7
  mmc_disable();
8
9
  for (n = 100; n; n--) spi_read_byte();    // 80 dummy clocks
10
11
  ty = 0;
12
  j=100;
13
do {
14
  if (mmc_send_cmd(CMD0, 0) == 1) {      // Enter Idle state 
15
    j=0;
16
    TimingDelay = 100;            // Initialization timeout of 1000 msec
17
18
    if (mmc_send_cmd(CMD8, 0x1AA) == 1) {  // SDv2? 
19
      for (n = 0; n < 4; n++){
20
        ocr[n] = spi_read_byte();    // Get trailing return value of R7 resp 
21
        }
22
      if (ocr[2] == 0x01 && ocr[3] == 0xAA) {            // The card can work at vdd range of 2.7-3.6V 
23
      
24
//        while (TimingDelay && mmc_send_cmd(ACMD41, 1UL << 30));  // Wait for leaving idle state (ACMD41 with HCS bit)
25
        while (TimingDelay) {  // Wait for leaving idle state (ACMD41 with HCS bit)
26
          mmc_send_cmd(CMD55, 0);
27
          if(mmc_send_cmd(ACMD41, 1UL << 30))
28
            break;
29
        }
30
                                ty = CT_SD2 | CT_BLOCK;
31
      }
32
    } else {        // SDv1 or MMCv3 
33
      if (mmc_send_cmd(ACMD41, 0) <= 1)   {
34
        ty = CT_SD1; 
35
        cmd = ACMD41;  // SDv1 
36
      } else {
37
        ty = CT_MMC; 
38
        cmd = CMD1;    // MMCv3 
39
      }
40
      while (TimingDelay && mmc_send_cmd(cmd, 0));      // Wait for leaving idle state 
41
    }
42
    while(TimingDelay && (mmc_send_cmd(CMD16, 512) != 0));
43
    if(!TimingDelay) ty = 0;
44
  } else { j--; }
45
  }while(j>0);
46
  fat.card_type = ty;
47
  mmc_disable(); 
48
49
  if( fat.card_type == 0 ){
50
    return FALSE;
51
  }
52
  #if (MMC_MAX_SPEED==TRUE)
53
    spi_maxSpeed();
54
  #endif
55
56
  return TRUE;
57
}

Um SDHC-Karte überhaupt zum laufen zu bewegen (besonders eine 
8GB-MicroSD) musste ich die ACMD41-Schleife noch um das vorherige Senden 
von CMD55 erweitern, so wie es in der Spec auch gefordert wird.

Die Abfrage auf CMD58 habe ich raus genommen, da diese von keiner meiner 
Karten anders als mit 05 (Illigal Command) beantwortet wird.
Bei meinen SDHC Karten mit 4 und 8GB hat das mit
1
ty = CT_SD2 | CT_BLOCK;
ganz gut funktioniert, aber jetzt habe ich eine extrememory 2GB bei der 
er auch in den SDv2-Block läuft die nur mit
1
ty = CT_SD2;
läuft. Also die Zugriffe der FAT-Funktionen klappen sonst halt nicht 
mehr.
Gibt es noch eine andere Möglichkeit als CMD58 hier eine Unterscheidung 
zu machen?

Eine 1GB Platinum hingegen läuft auch in diesen Block bleibt jedoch am 
ACMD41 hängen: es kommt immer 0x00 zurück, sie kommt also nie in den 
Idle-State.

Any Ideas? Gerade bezüglich des CT_SD2 bzw. CT_BLOCK, weil wenn dann nur 
noch die Platinum Karte nicht ginge wäre das zu verschmerzen...die 
scheinen ja eh etwas tricky zu sein.

Gruß
Fabian

von Fabian B. (fabs)


Lesenswert?

Noch eine Ergänzung:

wenn ich die CMD58 Abfrage vor der CMD55->ACMD41 Kombination sende 
bekomme ich eine "Antwort". Die Karten senden dann nicht mehr 05 
(Illegal Command) sondern immer 01 (Idle State). Wenn ich danach noch 4 
Byte lese bekomme ich für das CCS Bit aber immer 0, egal ob SDHC oder 
nicht HC.
Es muss doch noch eine Möglichkeit geben SDv2 von SDHCv2 Karten zu 
unterscheiden?!

Gruß
Fabian

von Michael R. (Gast)


Lesenswert?

Hallo,
hatte gerade mit meinem 8MHz-System Probleme, die SD-Karte zuverlässig 
zu initialisieren. Nachdem ich den SPi-Prescaler von 128 auf 64 geändert 
habe, gehts jetzt offenbar zuverlässig. Die Initialisierungs-SPI-Clock 
wird in der MMC.C fest mit fCPU/128 gesetzt.
Vielleicht wäre es sinnvoller dass diese in Abhängigkeit vom CPU-Takt 
gesetzt wird, der in irgendeinem h-file definiert wird.

Laut einigen Quellen müssen die Init-Takte mit 100-400kHz erzeugt 
werden, was beim 128er Teiler erst ab 12,8Mhz zutrifft. Vielleicht wäre 
es auch sinnvoller, beim AVR standardmäßig den 64er-Teiler zu nutzen. 
Das deckt besser die typischen Taktfrequenzen ab.

Michael

von Daniel R. (zerrome)


Lesenswert?

Hallo zusammen.

@ Fabian B. (fabs)
Hast Du einen PullUp an MISO?
Wie schnell ist dein Kontroller?
Die Init Routine hab ich selber nur abgeschaut,
die die ich selber geschrieben hatte ist raus geflogen,
obwohl die gut war...vielleicht mach ich das wieder rückgängig.


@ Michael R. (Gast)
Ja werde ich ändern.

Viele Grüße

Daniel

von Fabian B. (fabs)


Lesenswert?

@Daniel: Ich hab noch einen gravierenden Fehler in der Soft gefunden. 
Jetzt geht auch CMD58. Alle Karten initialisieren nun korrekt, soweit so 
gut.
Nur auf meiner MicroSDHC (8GB) kann ich zwar die Fat initialisieren und 
auch ffopen gibt ein Ok, aber ich bekomm keine Dateiinfos (filesize oder 
Daten). Dabei ging die Karte vorher ... ich find das aber noch raus 
(morgen) und werde die Routine dann posten.

Gruß
Fabian

von Daniel R. (zerrome)


Lesenswert?

>Alle Karten initialisieren nun korrekt...

Na das klingt doch schon mal gut.

von Fabian B. (fabs)


Lesenswert?

So.
 Ich habe habe jetzt die Init soweit dass alle meine Karte initialisiert 
werden. Getestet wurden:
 - Canon SD 16MB
 - Nokia MMC 32MB (2x)
 - extrememory MMC 256MB (mit FAT16 und FAT32)
 - Platinum SD 1GB (meldet sich als SDv2)
 - extrememory SD 2GB (meldet sich als SDv2)
 - SanDisk SDHC 4GB (Ultra II)
 - SanDisk MicroSDHC 8GB (2x)
 - Noname MicroSDHC 8GB

Hierfür musste ich zwei Änderungen an der mmc.c vornehmen.
Bei den Definitions ganz oben im File war das define für ACMD41 falsch.
Korrekt ist:
1
#define  ACMD41  (41)  // SEND_OP_COND (SDC)
vorher war dort (0x80+41) definiert.
Ich denke auch bei ACMD13 und ACMD23 müsste dieses (0x80) weg, aber da 
ich diese Kommandos nicht selbst brauchte und bisher keine Fehler 
diesbezüglich feststellte hab ich das erstmal so gelassen.

Die zweite Modifikation betrifft die Funktion mmc_init. Wie oben schon 
geschrieben hatte ich ein paar Karten die nicht sofort auf CMD0 
antworten, also habe ich hier eine Schleife drum gelegt. Auch bei 
anderen Kommandos war dies notwenig (CMD55->ACMD41, CMD58, CMD16).
Ich poste hier einfach mal die ganze Funktion:
1
unsigned char mmc_init (void){
2
3
  unsigned char cmd, ty, ocr[4];
4
  unsigned short n, j;
5
6
  spi_init();
7
  mmc_disable();
8
9
  for (n = 100; n; n--) spi_read_byte();    // 80+ dummy clocks
10
11
  ty = 0;
12
  j=100;
13
do {
14
  if (mmc_send_cmd(CMD0, 0) == 1) {      // Enter Idle state 
15
    j=0;
16
    TimingDelay = 100;            // Initialization timeout of 1000 msec
17
18
    if (mmc_send_cmd(CMD8, 0x1AA) == 1) {  // SDv2? 
19
      for (n = 0; n < 4; n++){
20
        ocr[n] = spi_read_byte();    // Get trailing return value of R7 resp 
21
        }
22
      if (ocr[2] == 0x01 && ocr[3] == 0xAA) {            // The card can work at vdd range of 2.7-3.6V 
23
        while (TimingDelay) {  // Wait for leaving idle state (ACMD41 with HCS bit)
24
          mmc_send_cmd(CMD55, 0);
25
          if(!mmc_send_cmd(ACMD41, 1UL << 30))
26
            break;
27
        }
28
29
        while(TimingDelay) {
30
        if (mmc_send_cmd(CMD58, 0) == 0x00) {    // Check CCS bit in the OCR 
31
          for (n = 0; n < 4; n++){
32
            ocr[n] = spi_read_byte();
33
            }
34
          ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;  // SDv2 
35
          break;
36
        }
37
        }
38
      }
39
    } else {        // SDv1 or MMCv3 
40
      if (mmc_send_cmd(ACMD41, 0) <= 1)   {
41
        ty = CT_SD1; 
42
        cmd = ACMD41;  // SDv1 
43
      } else {
44
        ty = CT_MMC; 
45
        cmd = CMD1;    // MMCv3 
46
      }
47
      while (TimingDelay && mmc_send_cmd(cmd, 0));      // Wait for leaving idle state 
48
    }
49
    if(ty != (CT_SD2 | CT_BLOCK)) {
50
      while(TimingDelay && (mmc_send_cmd(CMD16, 512) != 0));
51
    }
52
    if(!TimingDelay) ty = 0;
53
  } else { j--; }
54
  }while(j>0);
55
  fat.card_type = ty;
56
  mmc_disable(); 
57
58
  if( fat.card_type == 0 ){
59
    return FALSE;
60
  }
61
  #if (MMC_MAX_SPEED==TRUE)
62
    spi_maxSpeed();
63
  #endif
64
65
  return TRUE;
66
}

Was mir noch auffiel:
Laut Spec muss ein ACMD immer auf ein CMD55 folgen. Im SDv1 or MMCv3 
block wird nur so direkt ein ACMD41 versucht. Ich vermute, dass hier 
eigentlich auch ein CMD55 vorher noch sein müsste, da ich aber mit keine 
Karte, die diesen Block durchläuft Probleme hatte lass ich es so.

Vielleicht kannst du, Daniel, diese Funktion so bei dir einpflegen und 
mal testen.

Nicht direkt als Bug zu bezeichnen: ich hatte noch eine 
Unregelmässigkeit.
Bei den SanDisk MicroSDHC 8GB konnte ich die Karte korrekt 
initialisieren, Fat initialisieren und auch Fileopen lieferte ein Ok, 
die Datei hatte laut file.length jedoch eine grösse von 0 und auch ein 
"blindes" ffread() lieferte nur Schrott. Da auf der Karte auch vorher 
schon Daten waren habe ich sie dann mal formatiert und die Datei wieder 
drauf kopiert und dann ging's einwandfrei.
Gibt es da vielleicht Zugriffprobleme auf Dateien ab einer bestimmten 
"Position auf der Karte", also weit hinten? Und wäre es vielleicht 
sinnvoll ffopen failen zu lassen wenn die Dateigrösse 0 ist?

Ich verwende:
At90Can128, 10MHz, HC4050 als Pegelwandler, 3V3 Regler für SD Karte, 
HW-Spi

Gruß
Fabian

von recently (Gast)


Lesenswert?

Hallo,

ich habe ein Problem mit dem neuen Code:

Wenn ich das richtig verstehe, wartet die Funktion mmc_wait_ready 
lediglich solange, bis auf der Miso-Leitung H-Pegel anliegt:
1
static unsigned char mmc_wait_ready (void){
2
3
  TimingDelay = 50;
4
5
  do{
6
    if(   spi_read_byte() == 0xFF ) return TRUE;
7
  }while ( TimingDelay );
8
9
  return FALSE;
10
}

Zur Aktivierung der Karte wird also zunächst CS auf 0 gesetzt und dann 
getestet, ob Miso auf H-Pegel geht (oder bereits ist):
1
static unsigned char mmc_enable(){
2
      
3
   MMC_CS_LOW;
4
   if( !mmc_wait_ready() ){
5
       mmc_disable();
6
    return FALSE;
7
   }
8
9
   return TRUE;
10
}

Das funktioniert bei mir leider nicht. Meine Karte(n) liefert vor 
Absendung des CMD0 Kommandos immer L-Pegel. Aus diesem Grund kommt es 
bei mir nicht zur CMD0 Absendung. Habe die mmc_wait_ready erstmal 
auskommentiert, wäre für eine Erläuterung dankbar ...

Viele Grüße
recently

von Daniel R. (zerrome)


Lesenswert?

Hallo.

>getestet, ob Miso auf H-Pegel geht (oder bereits ist)

Miso sollte H sein, weil da ein PullUp dran sein sollte.
Ich muss das im Wiki unbedingt mal ändern.

Damit sollte das dann klappen.

Viele Grüße

Daniel

von recently (Gast)


Lesenswert?

Hallo Daniel,

vielen Dank für die schnelle Antwort. Habe den Schaltplan von meinem 
Pollin Net-IO mit SD-Karten-ADD-On untersucht und finde dort keinen 
Pullup.

Bin ein wenig irritiert, die Hardware funktionierte ja mit der alten 
Software, auf dem Oszilloskop sieht das Miso-Signal auch normal aus, 
schön rechteckig und ungefähr zwischen 0 und 3V. Aber es ist 0V, wenn 
die Karte herausgezogen oder gerade hereingesteckt wurde.

Was für ein Widerstand sollte da eingelötet werden ?

- recently -

von Daniel R. (zerrome)


Lesenswert?

Bei der alten Version war das mit dem wait anders gelöst.
Es sollte ein 10K Widerstand gegen +3,3 Volt sein.
Damit die Karte am DO Pin auf jeden Fall vor cmd0 auf high ist.
Siehe auch:
Dritter Unterpunkt.
http://www.mikrocontroller.net/articles/MMC-_und_SD-Karten#DOs_und_DON.27Ts_bei_der_Ansteuerung


Viele Grüße

Daniel

von Fabian B. (fabs)


Lesenswert?

Das kann auch ein Effekt der der Karte sein, dass die die Leitung 
schwach auf low zieht wenn sie eingesteckt wird und direkt Saft bekommt 
(evtl. noch mit Prelleffekten auf der Versorgung). Da ich die Versorgung 
der Karte bei mir immer erst einschalte, wenn die Karte im Slot 
detektiert wurde, konnte ich dieses Verhalten bei inzwischen ca. 15 
getesteten Karten nicht feststellen.

@Daniel R: hast du den mmc_init mal testen können?

Gruß
Fabian

von Daniel R. (zerrome)


Lesenswert?

Leider nein, hab diese Woche noch 2 Klausuren und es war Karneval :)
Komme ich aber bald dazu, danke das Du da soviel Mühe mit rein 
Investiert hast.

Viele Grüße

Daniel

von recently (Gast)


Lesenswert?

Hallo Daniel,

habe den 10k Widerstand eingebaut ... Unterschied wie Tag und Nacht. Die 
Initialisierung funktioniert jetzt sauber und reproduzierbar (ohne 
Pullup hatte ich mehrere CMD0-Wiederholungen, jetzt immer genau 1x). 
Sollte man Pollin mal mitteilen ... :-)

Vielen Dank für den Tipp !

Viele Grüße
recently

von johnn (Gast)


Lesenswert?

Haloo,
Ich bin nur Anfänger und ich möchte nur einfacher Programm machen. 
Programm macht neue Datei – zum Beispiel „1.txt“ und schreibt jede 10 
Sekunden Temperatur (es ist in string format). Jede Temperatur an neue 
Zeile. Zuerst möchte ich nur library 0.6.2 testen.

Ich habe SD-Karte, ATMega 168 – es ist durch MISO, MOSI, SCK und CS 
verbinden.
Jetzt teste ich Version 0.6.2. Ich habe AVR Studio 4.18, ich öffne 
main_simple.c, dann gebe ich Project -> Configuration Options – ich 
schreibe Frequency 16MHz (ich habe 16 MHz Krystal). Und dann 
programmierte ich den Prozessor. Ich lasse den Programm etwa 10 sekunden 
laufen. Aber es macht nichts. Die Karte ist leer. Mache ich etwas 
schlecht ? Muss ich noch etwas machen ? Die Karte ist normal formatiert 
in Windows – FAT.
Können Sei mir bitte helfen ? Vielen Dank.

von Daniel R. (zerrome)


Lesenswert?

Hallo,
läuft der ATMega 168 mit 3,3 Volt?
Läuft das Beispielprogramm ohne irgendwelche Änderungen?
Wie sieht die Schaltung aus?

Versuch immer in kleinen Schritten etwas auszuprobieren, bis es läuft 
und erweitere es dann erst.

Viele Grüße

Daniel

von johnn (Gast)


Lesenswert?

Atmega hatte 5Volt, jetzt läufte mit 3,3V aber es geht auch nicht.
Ich mache keine Änderungen - nur frequency.
Die Schaltung ist wie hier 
(http://www.mikrocontroller.net/articles/AVR_FAT32), aber keine HC4050 
(ich habe 3,3 Volt).

von Daniel R. (zerrome)


Lesenswert?

Hallo,
dann mach doch mal noch einen PullUp an MISO vom Kontroller. 
Beziehungsweise an DO der Karte.
Dann könntest Du noch mal versuchen in der mmc_config.h
1
#define MMC_MAX_SPEED     FALSE

zu setzen.

Und eventuell die mmc_init() zu benutzen die in folgendem Link 
angesprochen wird.

Beitrag "Re: MMC SD library FAT16 FAT32 read write"

Falls das alles nichts hilft, müsstest Du mal ein Foto vom Aufbau machen 
und hochladen, damit man sich eventuell ein bild von möglichen 
Fehlerquellen machen kann.

Du solltest auch mehrere Karten ausprobieren ob vielleicht nur eine 
bestimmte nicht funktioniert.

Viele Grüße

Daniel

von C. H. (hedie)


Lesenswert?

Hallo zusammen

Ich habe ein Problem mit der AVR Fat32 Library

http://www.mikrocontroller.net/articles/AVR_FAT32

Zur Hardware:

Ich verwende einen Atmega16 mit 12MHz Quarz
Am Hardware SPI Hängt die SD Karte (micro SD)
Der Atmega wird mit 3,3V Betrieben.

Nun das Problem

Die Library funktioniert grundsätzlich sehr gut... Ich habe die Dateien 
1:1 übernommen uns es klappte auf anhieb.

Doch ich habe das problem, das wenn ich z.B. die Datei bild.bmp öffnen 
lassen will mit der Lib, dann verwende ich folgenden Code
1
while (FALSE==mmc_init()){  //Karte Initialisieren
2
      nop();
3
    }
4
  Out1_1;
5
  if(TRUE == fat_loadFatData()){
6
    unsigned char file_name[9]="bild.bmp";
7
8
    if(MMC_FILE_EXISTS == ffopen(file_name)){
9
      Out1_0;
10
      // Setzen einer Variable und dann runterzaehlen geht am schnellsten !
11
      seek=file.length;
12
      // Lesen eines chars und Ausgabe des chars.
13
              // Solange bis komplette Datei gelesen wurde.
14
              while(ucBufferCounter != 56) //Daten auslesen
15
              {
16
                 ucBuffer[ucBufferCounter] = ffread();
17
                 --seek;  //Byte Zähler
18
                 ucBufferCounter++;
19
              } //56Bytes Buffer auslesen
20
    }
21
22
  }

nicht von den 56Bytes irritieren lassen... das spielt derzeit keine 
rolle!


Doch wenn ich diesen Code ausführen lasse, dann meldet der Code das Die 
Datei existiert jedoch erstellt er selbige auf der Karte.

Wenn ich Die karte also in den PC einschiebe, befindet sich zweimal die 
Datei bild.bmp im Root verzeichniss... Windows motzt nun also und ich 
muss die Karte formatieren...

Wass jedoch prblemlos geht, ist eine von der Lib erstellte Datei lesen 
oder zu erweitern... Auch mit dem Computer... Aber es kann ja nicht 
sein, das ich immer mit dem AVR eine Datei erstellen muss und diese Dann 
am Computer bearbeiten muss. Dies geht sowiso nur bei txt dateien.

Getestet habe ich den Code mit mehreren Karten. An dennen liegt es also 
nicht! An der Lib config habe ich nichts verändert!

Was auch merkwürdig ist, das bei dem Beispielcode von hier
http://www.mikrocontroller.net/articles/AVR_FAT32#Der_Code
steht beim Filename "man beachte die Grossbuchstaben" aber es hat im 
beispiel nur kleinbuchstaben.

Hat jemand eine idee wo hier der wurm drinn sein könnte?

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ich komme grad nicht dazu ne neue Version zusammen zu packen in der auch 
die neue Initialisierungsfunktion ist und auch die neue 
fat_loadFiledataFromCluster.
1
//***************************************************************************************************************
2
// prueft auf lange dateinamen (lfn), ermittelt anhand des langen dateinamens den kurzen. nur der kurze
3
// enthaelt die noetigen informationen um die datei lesen zu koennen. ist der gesuchte dateiname gefunden
4
// aber im naechsten sektor/cluster ermittelt die funktion selbstaendig diese und holt die informationen !
5
//***************************************************************************************************************
6
static unsigned char fat_loadFileDataFromCluster(unsigned long int sec , unsigned char name []){
7
8
    unsigned short row;    // um durch zeilen zu gehen, eigentlich erstes byte einer reihe...
9
    unsigned char sectors;  // um durch sektoren zu zaehlen, sectors+sec = tatsaechliche sektornummer (absoluter sektor)
10
    unsigned char i;      // um durch eine zeile/reihe zu laufen
11
    unsigned char j;      // laufvariable fuer sfn
12
13
    // diese variablen muessen statisch sein, weil ein lfn eintrag auf 2 cluter aufgeteilt sein kann !
14
    static unsigned char checksum = 0;  // die kurze dateinamen checksumme, die ausgelesene.
15
    static enum flags { wait=0,start,readout } lfn_state;
16
    static unsigned char match = 0;    // treffer bei datei namen vergleich zaehlen
17
18
    const unsigned char map[13]={1,3,5,7,9,14,16,18,20,22,24,28,30};    // index von map ist index des zu pruefenden bytes und inhalt ist index des zu pruefenden bytes in der reihe
19
    const unsigned char name_length = strlen((char *)name)-1;      // es wird die laenge des dateinamen zum vergleichen benoetigt!
20
21
    sectors = 0;
22
23
    // 5 moegliche zustaende im inneren der beiden schleifen...
24
    do{                      // sektoren des clusters pruefen
25
    row=0;                    // neuer sektor, dann reihen von 0 an.
26
    mmc_read_sector(sec+sectors,fat.sector);  // laed den sektor sec auf den puffer fat.sector
27
    fat.lastSector = file.currentSectorNr;    // sichern der alten sektor nummer
28
    file.currentSectorNr = sec + sectors;    // setzen des aktuellen sektors
29
    do{                      // reihen des sektors pruefen
30
      // 1.) nach einem eintrag mit 0x00 kommt nix mehr => restlicher cluster leer!
31
      if( fat.sector[row]==0x00 ){
32
        return FALSE;
33
      }
34
      // 2.1) ist eintrag ein lfn eintrag?   siehe: http://en.wikipedia.org/wiki/File_Allocation_Table#Long_file_names
35
      if( (fat.sector[row]&0x40) == 0x40 && fat.sector[row+11] == 0x0F && fat.sector[row] != 0xE5 ){                                      // ist lfn eintrag, jetzt pruefen...
36
        lfn_state = start;
37
      }
38
      // 2.2) ist eintrag ein sfn eintrag? 
39
      if( (fat.sector[row+11] == 0x10 || fat.sector[row+11] == 0x20) && fat.sector[row] != 0xE5 && lfn_state != readout){
40
        // vergleich von sfn dateinamen
41
        i = 0; j = 0;
42
        do{          
43
          if( fat.sector[row+i] == 0x20 ){     // ueberspringen von leerzeichen auf der karte
44
            i++; continue;
45
          }
46
          if( name[j] == '.' ){           // ueberspringen von punkt im dateinamen
47
            if( i <= 7) break;
48
            j++; continue;
49
          }
50
          if( fat.sector[row+i] != toupper(name[j]) )  break;
51
          i++; j++;
52
        }while(i<11);
53
        // datei gefunden
54
        if( i == 11 && j != 11){
55
          lfn_state = readout;                                      // ist lfn eintrag, jetzt pruefen...
56
          checksum = fat_lfn_checksum( &fat.sector[row] );
57
        }
58
      } 
59
      // 3.) lfn gefunden, jetzt verarbeiten. raussuchen der richtigen bytes und direkter vergleich mit dem original.
60
      if( lfn_state == start || match !=0 ){
61
        i=12;
62
        do{
63
          if( fat.sector[row+map[i]]!=0x00 && fat.sector[row+map[i]]!=0xFF ){  // gueltiger buchstabe. ist gueltig wenn, es nicht 0 oder ff ist.
64
            if( fat.sector[row+map[i]] == name[name_length-match] ){    // vergleich mit original, ist treffer?
65
              match += 1;                          // bei treffer index zaehler fuer vergleich hochzaehlen
66
            }
67
            else {            // wenn ein gueltiger buchstabe keinen treffer verursacht, ist es die falsche datei !
68
              lfn_state = wait;     // zurueck zu ausgangszustand
69
              match = 0;        // treffer zurueck setzen
70
              break;          // weitere pruefung nicht noetig da eintraege ungleich!
71
            }
72
          }
73
        }while(i--);            // zeichen index einer zeile/reihe abarbeiten
74
        // komplette uebereinstimmung und sequenz id 1 ==> datei gefunden !!
75
        if( (name_length-match) == -1 && (fat.sector[row]&0x01) == 0x01){
76
          lfn_state = readout;      // langer dateiname stimmt ueberein, jetzt zustand wechseln.
77
          match = 0;            // vergleich index zurueck setzen, damit nicht wieder in diesen zustand gewechselt wird.
78
          checksum = fat.sector[row+13];  // checksumme sichern zum vergleich mit der errechneten anhand des kurzen dateinamens. in naechstem zustand vergleich.
79
        }
80
      }
81
      // 4.) gesuchte reihe auf stuct file laden zum weiter verarbeiten. das ist der sfn eintrag, mit dem firstCluster, der laenge usw...
82
      if( lfn_state == readout && fat.sector[row+11] != 0x0F ){
83
        lfn_state = wait;
84
        fat_loadRowOfSector(row);
85
        file.row = row>>5;                  // reihe sichern, ist fuer ffrm wichtig
86
        if(checksum==fat_lfn_checksum(&fat.sector[row])){  // pruefen ob checksumme stimmt...wenn ja alles klar :)
87
          file.entrySector = file.currentSectorNr;    // sichern des sektors in dem der sfn dateieintrag steht.
88
          return TRUE;
89
        }
90
      }
91
92
      }while( (row+=32) < 512 );      // mit row+32 springt man immer an die 1. stelle einer reihe (zeile) und das durch einen ganzen sektor
93
    }while( ++sectors < fat.secPerClust );  // geht durch sektoren des clusters
94
95
    return FALSE;              // datei nicht gefunden, zumindest in diesem cluster...
96
}

Diese Funktion solltes Du mal test weise in der fat.c austauschen.

>man beachte die Grossbuchstaben

Die Kommentare in den Sourcen sind nicht immer aktuell ^^

Sag mir mal ob in der mmc_config.h
1
MMC_LFN_SUPPORT TRUE
ist.


Viele Grüße

Daniel

von C. H. (hedie)


Lesenswert?

Daniel R. schrieb:
> Die Kommentare in den Sourcen sind nicht immer aktuell ^^

Kein Problem :)

Vielen Dank für die Antwort

Ich habe LFN Support auf True
und auch MMC File Exists auf True

Ich verwende übrigens die neuste Version aus dem SVN

habe besagten Code ersetzt jedoch kommen nun folgende Meldungen

../fat.c:195: error: 'struct Fat' has no member named 'lastSector'
../fat.c:195: error: 'struct File' has no member named 'currentSectorNr'
../fat.c:196: error: 'struct File' has no member named 'currentSectorNr'
../fat.c:255: error: 'struct File' has no member named 'currentSectorNr'

Anscheinend ist das Struct geändert worden von dir :)

von Daniel R. (zerrome)


Lesenswert?

Hm, ja stimmt.
Die Version aus dem SVN ist nicht die neuste.

Nimm diese:

http://www.mikrocontroller.net/attachment/101158/0.6.2.zip

Muss das mal ins SVN hochladen...

von Daniel R. (zerrome)


Lesenswert?

Ach ja und in der 0.6.2 musst Du noch die besagte Funktion tauschen...

Muss das die Tage mal alles sortieren^^

von C. H. (hedie)


Lesenswert?

Vielen dank für den Hinweis und die neue Lib

Was meint der Compiler mit undefined reference timing delay?

Muss ich diese Funktion bereitstellen?

von Daniel R. (zerrome)


Lesenswert?

Es muss eine
1
volatile unsigned char   TimingDelay;  // fuer mmc.c

Variable im Programm geben die in 10 ms Intervallen runtergezählt wird 
bis 0. Wenn Du Dich an der main_simple.c orientierst sollte das kein 
Problem werden.

von C. H. (hedie)


Lesenswert?

Hat geklappt Danke!

Deine Lib ist echt Genial!!!

Hoffentlich lädstd du bald die neue Version hoch :)

von Daniel R. (zerrome)


Lesenswert?

Schön das es geklappt hat :)

Viele Grüße

Daniel

von C. H. (hedie)


Lesenswert?

Ich habe mit deiner Neusten Version ein sehr merkwürdiges aber 
reproduzierbares verhalten entdeckt.

Ich möchte auf der Speicherkarte überprüfen ob die Datei logfile.txt 
existiert...

Das mache ich wie folgt:
1
unsigned char file_name_2[]="logfile.txt";
2
3
  if(ffileExsists(file_name_2))
4
  {
5
    text_neu("OK",90,90,1,0,0,255);
6
  }
7
  else
8
  {
9
    text_neu("ERROR",90,90,1,255,0,0);
10
  }

Problem -> Die funktion liefert immer Error zurück obwohl die Datei auf 
der Speicherkarte liegt (habe auch grossklein schreibung geachtet!) LFN 
ist aktiviert.

Prüfe ich hingegen ob die Datei test.bmp existiert, klappt der test 
einwandfrei. Beide Dateien beinhalten etwas. sind also nicht 0Byte 
gross!

Nun das ganz spezielle...

Möchte ich nun also die Datei Lesen (logfile.txt) wass ja eigentlich 
nicht gehen sollte, so wird diese angelegt und es befinden sich wieder 
zweimal die selben dateien auf der Karte. Wichtig hier zu beachten ist, 
das die Lib die neue Datei mit Grossbuchstaben erstellt egal ob ich der 
Funktion kleibuchstaben übergeben habe.

Könnte dies ein hinweis darauf sein, das in dieser funktion nicht auf 
LFN geachtet wird?

Vielleicht sagt dir meine Fehlerbeschreibung ja etwas...

Ansonsten keine Probleme :)

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ja klingt irgendwie danach:

Beitrag "Re: MMC SD library FAT16 FAT32 read write"

Ersetze die Funktion in der fat.c durch die Funktion aus dem Post.
Benutzt Du die Version 0.6.2 ? Da sollte wenn Du die Datei zum lesen 
öffnest auf jeden Fall keine zweite Datei mit dem selben Namen angelegt 
werden.

Viele Grüße

Daniel

von C. H. (hedie)


Lesenswert?

Hallo Daniel

Ja ich habe die Funktion ersetzt... Ja ich verwende die Version 0.6.2

Ich habe das Problem gefunden...

Es scheint so, als ob die Funktion File Exists nur mit kurzen Dateinamen 
klar kommt...

Dies stört mich nicht weiter, da ich ja darauf achten kann...

Aber wollte dir halt dennoch den hinweis geben :)

von Daniel R. (zerrome)


Lesenswert?

Wenn Du mal in ffileExsists reinschaust, dann siehst du da, dass genau 
das gleiche gemacht wird, zum prüfen ob es die Datei gibt, wie beim 
öffnen.

von C. H. (hedie)


Lesenswert?

Dann ist es allerdings etwas merkwürdig das LFN nicht unterstützt wird 
obwohl ich den Schalter auf True habe. Das selbe ist es mit SDHC karten

Ich habe den schalter auf True

Aber 8GB Karten werden nicht initialisiert.... (FAT)

von Daniel R. (zerrome)


Lesenswert?

Hast Du die hier gepostete mmc_init Version benutzt?
Beitrag "Re: MMC SD library FAT16 FAT32 read write"

Hast Du die hier gepostete fat_loadFileDataFromCluster Version benutzt?
Beitrag "Re: MMC SD library FAT16 FAT32 read write"

Damit geht das auf jeden Fall.

Viele Grüße

Daniel

von Daniel R. (zerrome)


Lesenswert?

Ach was mir noch einfällt zu

>Ja ich verwende die Version 0.6.2

Das kann nicht sein. In der 0.6.2 ist der Schalter für SDHC raus 
geflogen.

von C. H. (hedie)


Lesenswert?

Daniel R. schrieb:
> Das kann nicht sein. In der 0.6.2 ist der Schalter für SDHC raus
> geflogen.

Ohhh.... schande... Tut mir leid... ja du hast recht... ich habe auch 
keinen.

Daniel R. schrieb:
> Hast Du die hier gepostete mmc_init Version benutzt?
> Beitrag "Re: MMC SD library FAT16 FAT32 read write"
>
> Hast Du die hier gepostete fat_loadFileDataFromCluster Version benutzt?
> Beitrag "Re: MMC SD library FAT16 FAT32 read write"
>
> Damit geht das auf jeden Fall.
>
> Viele Grüße

Ich habe diese Version von der du mir den link gesendet hast.

von Daniel R. (zerrome)


Lesenswert?

Ok, Du brauchst die Version 0.6.2 hier aus dem Thread und dann musst Du 
die beiden Funktionen austauschen. Die Beiden Funktionen aus den Links 
die ich gepostet hab. Dann wird es klappen. Bin wie gesagt noch nicht 
dazu gekommen die einzubauen und das ins SVN hochzuladen.

Viele Grüße

Daniel

von C. H. (hedie)


Lesenswert?

Ok

Vielen Dank

Ich werde die Anpassungen vornehmen und eventuelle probleme wieder 
fragen wenn ich darf :)

Ich denke das ich dann auch mit den Verzeichnissen arbeiten kann... Das 
klappt mommentan auch noch nicht

von johnn (Gast)


Lesenswert?

Und hast du in library behandelt Ergennung der Karte und Schutz von 
Überschreibung ?

von johnn (Gast)


Lesenswert?

und wo muss ich die Karte anschliessen ? Ich habe ATMega 168.
in mmc.h schreibt mann
1
    #if defined (__AVR_ATmega168__)
2
                #define SPI_MISO                        4  //Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist
3
                #define SPI_MOSI                3  //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist
4
                #define SPI_Clock                       5  //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk)
5
                #define SPI_SS                          2  //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist (CS)
6
        #endif
 - CS (Karte) - PB2 (ATMEga168)


und hier in der Tabelle 
http://www.mikrocontroller.net/articles/AVR_FAT32
schreibt man CS (Karte) - PB1 (ATMEga168)


Was ist richtig ?

von Daniel R. (zerrome)


Lesenswert?

Hallo,
die Tabelle ist so zu lesen:

Pin 1 der SD/MMC Karte soll an Pin 15 des ATmega168
Pin 2 der SD/MMC Karte soll an Pin 17 des ATmega168
...
...


Bei der DIP Version des ATmega168 sieht man im Datenblatt, dass Pin 15 
des IC der Port B1 des Kontrollers ist.

>Und hast du in library behandelt Ergennung
>der Karte und Schutz von Überschreibung ?

Du meinst ob eine Karte im Slot steckt und der Hardware Schreibschutz an 
ist?
Ja da ist was in der Lib, weiß aber nicht genau ob das auf Anhieb 
funktioniert.



Viele Grüße

Daniel

von Daniel R. (zerrome)


Lesenswert?

Ach, sorry...
Das was in den defines steht ist richtig. Hab gerade erst verstanden was 
Du meinst.

CS der Karte soll an PB2 vom ATmega168

von Kurt B. (kurt)


Lesenswert?

Kurt Bohnen schrieb:
> Leider funktioniert trotz MISO PullUP nur eine der 3 Karten. Mit der
> 0.5.9C hatten die alle funktioniert.
> Schade dass ich keine Zeit zur Fehlersuche habe.

Heute hatte ich Zeit. Das Problem war wohl, das ich "alten" Code aus dem 
SVN genommen hatte. Mit dem aktuellen Code und den Patches aus dem 
Thread hier funktionieren jetzt alle Karten!

Ein Problem bleibt immer noch:
Ich schreibe 921600 Byte auf die Karte. Kontrolle mit Win XP: Dateigröße 
und Inhalt OK. Dann nach checkdisk: Datei ist 4kB größer weil Datenmüll 
am Ende angehängt wurde.
Das passiert aber nur bei FAT32 formatierten Karten. Bei FAT16 gibt es 
keine Probleme. LFN hat keinen Einfluss.

Mfg,
Kurt

von Sven S. (schwerminator)


Lesenswert?

Moin! Ich verzweifel hier mal wieder an der Ansteuerung einer 
MicroSD-Karte (habe schon zwei verschiedene probiert). MCU ist ein 
AT90CAN128, Pegelwandler ein MAX3002. Die Verdrahtung habe ich schon 
hundertmal geprüft. MISO-Pullup (10k) habe ich auch.

Ich schaffe nicht einmal die mmc_init(). spi_read_byte() gibt immer nur 
0 zurück. Nach dem Timeout wird dann abgebrochen. Was kann ich noch 
machen, bin völlich ratlos?

Ich habe die neueste Version im Einsatz inkl. den Modifikationen aus den 
Posts hier.

von Daniel R. (zerrome)


Lesenswert?

Hm, mach doch mal ein Foto vom Aufbau.

>habe schon zwei verschiedene probiert

Wenn das nicht total außergewöhnliche Karten sind sollten die schon 
gehen.

>Nach dem Timeout wird dann abgebrochen.

Also die Timer Einstellungen sind richtig? Ist vielleicht der Timer zu 
schnell eingestellt? Überprüf mal ob die Zeiten des Timers stimmen.
Ich mache die Einstellungen um nicht nachdenken zu müssen mit 
http://clsql.med-info.com/download.html

>Ich schaffe nicht einmal die mmc_init()

Klingt für mich irgendwie nach Hardware Problem

Viele Grüße

Daniel

von Kurt B. (kurt)


Lesenswert?

Daniel,
hast du eine Idee wo mein Problem liegt oder sonst jemand? Ich bin doch 
wohl nicht der einzige, der seine Karten mal mit chkdsk geprüft hat?

Mfg,
Kurt

von Daniel R. (zerrome)


Lesenswert?

Hallo Kurt,
also ich würde mal vermuten, dass da die 2. Fat dran schuld ist.

Hast Du die Möglichkeit die Karte mal so zu formatieren, dass nur eine 
Fat angelegt wird?

Sonst kann ich mir das eigentlich nicht erklären. Besonders, weil es nur 
bei Fat32 auftritt. Bis auf die Fat Einträge selbst ist Fat16 und Fat32 
nämlich identisch.

Unter Linux würde formatieren mit nur einer Fat so aussehen:
1
mkdosfs -v -F32 -f1 -s4 -I /dev/sdb

Der Befehl erstellt ein Fat32 Dateisystem mit nur einer Fat und 4 
Sektoren pro Cluster auf dem Device sdb.

Viele Grüße

Daniel

von Kurt B. (kurt)


Lesenswert?

Linux habe ich nicht. Aber ich könnte den SD Formatter 3.0 probieren.

von Sven S. (schwerminator)


Angehängte Dateien:

Lesenswert?

So ich habe jetzt mal alle Signale vor (5V, high) und hinter (3V, low) 
dem Pegelwandler aufgenommen. Herausgekommen ist der Anhang. Die kurzen 
Puls bei MISO low sind etwa 10ns lang. Kann jemand bei der Deutung des 
Bildes helfen?

von Sven S. (schwerminator)


Angehängte Dateien:

Lesenswert?

So ich habe jetzt mal je einen SPI Interpreter auf die low und high side 
gepackt. Auf der low side können auch Bytes entziffert werden - 
natürlich nicht auf der high side. Machen die Bytes Sinn? Ist der 
Pegelwandler defekt?

von Sven S. (schwerminator)


Lesenswert?

Jetzt fall ich gleich vom Glauben ab: Wenn der LogicAnalyser 
angeschlossen ist, funktioniert scheinbar alles, d.h die Test-Datei wird 
geschrieben (obwohl die aufgezeichneten Kurven anderes schließen 
lassen), ziehe ich ihn ab, geht nix mehr. Wodurch lässt sich so ein 
Verhalten erklären?
Ich habe spontan an das hier gedacht: 
http://www.eevblog.com/2011/03/11/eevblog-155-itead-studio-pcb-prototype-goof/ 
Aber ein Massefehler kann ich eigentlich ausschließen. Irgendwelche 
Ideen?

Vielen Dank im Vorraus und entschuldigung für die vielen Posts in Folge.

Gruß Sven

von Kurt B. (kurt)


Lesenswert?

Wenn ich die Karte mit dem SD Formatter 3.0 formatiere tritt das Problem 
nicht mehr auf. Aber gibt es nicht einen Workaround für die Firmware?


Mfg,
Kurt

von Daniel R. (zerrome)


Lesenswert?

Hallo.

@ Sven S. (schwerminator)

Hast du abblock Kondensatoren an allen IC's?
Was benutzt Du als Pegelwandler?


@ Kurt Bohnen (kurt)

Es wird dafür keinen Workaround geben. Das würde nämlich bedeuten, dass 
alle Fat Operationen zwei mal gemacht werden müssten. Die zweite Fat ist 
eigentlich gedacht um zu schauen ob es einen Unterschied gibt. Gibt es 
den muss wohl ein Fehler vorliegen. Korrigieren kann man den dann aber 
noch nicht.

Eventuell eine Alternative zu dem normalen check disk suchen.


Viele Grüße

Daniel

von Sven S. (schwerminator)


Lesenswert?

Abblockkondensatoren sind reichhaltig verbaut. Als Pegelwandler benutze 
ich einen MAX3002. Einen solchen habe ich schonmal erfolgreich mit einer 
SD-Karte betrieben, allerdings ohne MISO-Pullup, ich werde das Gefühl 
nicht los, dass sich MAX3002 und der Pullup aus welchen Gründen auch 
immer nicht vertragen. In meiner jetzigen Schaltung ist der Pullup mit 
10k dimensioniert auf der 3V-Seite des Wandlers, was jedoch 
grundsätzlich richtig sein müsste...

Gruß Sven

von Daniel R. (zerrome)


Lesenswert?

Hm, ja eigentlich schon...
Da fällt mir grad auch nix mehr zu ein.

Viele Grüße

Daniel

von Kurt B. (kurt)


Lesenswert?

Daniel R. schrieb:
> @ Kurt Bohnen (kurt)
>
> Es wird dafür keinen Workaround geben. Das würde nämlich bedeuten, dass
> alle Fat Operationen zwei mal gemacht werden müssten. Die zweite Fat ist
> eigentlich gedacht um zu schauen ob es einen Unterschied gibt. Gibt es
> den muss wohl ein Fehler vorliegen. Korrigieren kann man den dann aber
> noch nicht.
>
> Eventuell eine Alternative zu dem normalen check disk suchen.

OK. Dann muss ich diesmal zu Elm Chans lib wechseln. Die ist zwar 
deutlich größer aber in dieser Hinsicht toleranter.

Trotzdem vielen Dank!

Mfg,
Kurt

von Daniel R. (zerrome)


Lesenswert?

In Chans Lib wird die zweite Fat auch nicht beschrieben, da hast Du das 
gleiche Problem.

Das hat ja auch nix mit Tolerant zu tun. Sondern mit dem Unsinn zwei Fat 
Tabellen führen zu müssen anstelle von ordentlichen Codes um Fehler zu 
beheben. Die Idee einfach alles doppelt da hin zu schreiben ist ein 
Repetition Code und ne ganz große Glanzleistung von MS...

Du hast ja geschrieben, dass die Daten korrekt sind und nach einem check 
disk erst falsch. Vielleicht sind die ja schon vorher falsch? Poste doch 
mal die Änderungen die du gemacht hast, vielleicht kann ich dann mehr 
dazu sagen.


Viele Grüße

Daniel

von Kurt B. (kurt)


Lesenswert?

Ich bin mir jetzt fast sicher dass das FAT32 Problem bei Chan nicht 
auftritt, werde das aber nochmal prüfen.

Daniel R. schrieb:
> ganz große Glanzleistung von MS...
Da gebe ich dir Recht!

Ich kann nicht ausschließen dass jemand mein Projekt benutzt der seine 
SD-Card mit FAT32 und Windows formatiert. Wenn er dann aus welchem Grund 
auch immer checkdisk laufen lässt und die neu angelegten Dateien mit 
Müll volgestopft werden ist das weniger schön...

Daniel R. schrieb:
> Poste doch
> mal die Änderungen die du gemacht hast

Keine, nur die Portdefinitionen. Dann einfach eine neue Datei erstellen, 
900kB reinschreiben und schließen.

Ich melde mich später nochmal mit mehr Details.
Mfg,
Kurt

von JVogel (Gast)


Lesenswert?

Muss ich hier SPI verwenden oder kann ich das auch an andere Pins 
hängen?

von Daniel R. (zerrome)


Lesenswert?

Hallo.

@ JVogel (Gast)

Kannst auch an andere Pins hängen, musst dann aber software SPI benutzen 
und einschalten in der config. Zudem musst Du dann natürlich auch die 
richtigen Pins einstellen in der mmc.h

von JVogel (Gast)


Lesenswert?

OK danke, ich probier das mal die Tage aus

von Sven S. (schwerminator)


Lesenswert?

Hallo nochmals. Ich habe noch ein paar Tests gemacht:
- Auch ohne Pullup klappts nicht ohne LogicAnalyser
- Zusätzlicher 100n bringt ebenfalls nicht den gewünschten Erfolg
- Folgende Leitungen auf der High-Side des Pegelwandlers müssen an den 
LA geklemmt sein, damit es funktioniert: CS, SCK und MOSI (+ GND) - 
sprich alle Leitungen in Richtung der SD. Die Eingangsimpedanz des LA 
ist wie folgt: 200K Ohms, paralleled by <5pF.

Welche Schlüsse kann ich aus der Information ziehen?

von JVOGEL (Gast)


Lesenswert?

Bei mir hängt das programm bei  mmc_enable(); nach dem SPI_INIT

mmc_send_cmd(CMD0, 0)
->if ( FALSE == mmc_enable() )

dort bleibt es hängen woran kann das liegen?

Hab einen Atmega32@16mhz

Timer :
1
  TCCR0 = (1<<CS02) | (1<<CS00) | (1<<WGM01);
2
  TCNT0 = START_TCNT;
3
  OCR0 = TOP_OCR;
4
5
ISR (TIMER0_COMP_vect)
6
{
7
  TimingDelay = (TimingDelay==0) ? 0 : TimingDelay-1;
8
    
9
}

mmc.h
1
  #define MMC_Write     PORTC  //Port an der die MMC/SD-Karte angeschlossen ist also des SPI
2
  #define MMC_Read     PINC
3
  #define MMC_Direction_REG DDRC
4
5
  #if defined (__AVR_ATmega32__)
6
    #define SPI_MISO       3  //Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist
7
    #define SPI_MOSI        2  //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist
8
    #define SPI_Clock       1  //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk)
9
    #define SPI_SS          0  //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist (CS)
10
  #endif

mmc_config.h
1
    //#####################################################################################
2
  // WICHTIGE SCHALTER
3
4
  // schalter die den funktionsumfang aendern bzw, den funktionsumfang einiger funktionen :)
5
  #define MMC_WRITE       TRUE  // TRUE, dann mit write unterstuetzung, wenn FALSE dann read only !
6
  #define MMC_OVER_WRITE     FALSE  // TRUE und MMC_WRITE TRUE, dann kann ffwrite dateien ueberschreiben, wenn FALSE dann nur normales schreiben. um an eine datei anzuhaengen ist MMC_OVER_WRITE TRUE nicht noetig!
7
  #define MMC_MULTI_BLOCK   FALSE  // TRUE und MMC_OVER_WRITE FALSE, dann werden multiblock schreib/lese funktionen benutzt. ist schneller, wird aber moeglicherweise nicht von allen karten unterstützt. wenn FALSE ist normale operation
8
  #define MMC_ENDIANNESS_LITTLE   TRUE  // TRUE, dann ist der code auf littleendian ausgelegt. AVR ist littleendian. code ist auf littleendian optimiert!! siehe: http://de.wikipedia.org/wiki/Endianness
9
  #define MMC_LFN_SUPPORT    FALSE  // TRUE, dann mit unterstuetzung fuer lange dateinamen. kostet wenn read und write benutzt wird um die 800 bytes flash...
10
  #define MMC_RM_FILES_ONLY  TRUE  // TRUE ,MMC_WRITE TRUE und MMC_RM TRUE, dann wird die funktion ffrm so mit kompiliert, dass sie nur dateien loeschen kann. wenn FALSE und MMC_WRITE TRUE, dann kann die funktion dateien und ordner rekursiv loeschen !
11
12
  // schalter die explizit funktionen mit kompilieren oder nicht!
13
  #define MMC_TIME_STAMP     FALSE   // TRUE, dann werden die funktionen fat_getTime und fat_getFreeBytes mit kompiliert. siehe auch abschnitt: ZEIT FUNKTIONEN, weiter unten
14
  #define MMC_RM         FALSE  // TRUE und MMC_WRITE TRUE, dann wird die funktion ffrm mit kompiliert.
15
  #define MMC_SEEK      TRUE  // TRUE,dann wird die funktion ffseek mit kompiliert. mit dieser funktion kann man in einer geoeffneten datei vor und zurueck spulen. nur in kombination mit MMC_OVER_WRITE TRUE kann in einer datei ueberschrieben werden.
16
  #define MMC_MKDIR      FALSE  // TRUE und MMC_WRITE TRUE, dann wird die funktion ffmkdir mit kompiliert. mit dieser funktion kann man ordner anlegen.
17
  #define MMC_GET_FREE_BYTES  FALSE  // TRUE, dann wird die funkton fat_getFreeBytes mit kompiliert. mit dieser funktion kann der freie platzt auf der karte ermittelt werden
18
  #define MMC_LS        FALSE  // TRUE, dann wird die funktion ffls mit kompiliert. mit dieser funkion kann man die dateien auf der karte anzeigen lassen
19
  #define MMC_CD        FALSE  // TRUE, dann werden die funktionen ffcd und ffcdLower mit kompiliert. mit diesen funktionen kann man in ein verzeichnis wechseln oder aus einem verzeichnis ein verzeichnis hoeher wechseln.
20
  #define MMC_FILE_EXSISTS  FALSE  // TRUE, dann wird die funktion ffileExsists mit kompiliert. mit dieser funktion kann geprueft werden, ob es die datei im aktuellen verzeinis gibt !
21
  #define MMC_WRITE_STRING  TRUE  // TRUE und MMC_WRITE TRUE, dann wird die funktion ffwrites mit kompiliert. mit dieser funktion koennen strings auf die karte geschrieben werden.
22
  #define MMC_WRITEN      FALSE  // TRUE  und MMC_WRITE TRUE, dann wird die funktion ffwriten mit kompiliert.  mit dieser funktion koennen mehrere zeichen auf die karte geschrieben werden!
23
24
  // vorsicht, da die variable die die sektoren zaehlt ein short ist (MMC_MAX_CLUSTERS_IN_ROW*fat.secPerClust) !!
25
  #define MMC_MAX_CLUSTERS_IN_ROW 256   // gibt an wie viele cluster am stueck ohne fat-lookup geschrieben bzw gelesen werden können, wenn die fat nicht fragmentiert ist !
26
27
//#####################################################################################
28
  // SPI EINSTELLUNGEN
29
30
  // wenn MAX_SPEED FALSE dann wird die SPI bus geschwindigkeit nicht hoch gesetzt. ist zum testen von hardware die nicht richtig läuft
31
  #define MMC_MAX_SPEED     TRUE
32
  #define MMC_STATUS_INFO   FALSE
33
34
  // software spi? wenn TRUE muessen in der mmc.h noch die pins eingestellt werden ueber die die spi kommunikation laufen soll
35
  // es werden nur pins an einem port unterstuetzt !
36
  #define MMC_SOFT_SPI   TRUE

von JVOGEL (Gast)


Lesenswert?

VCC ist 2,73V, Atmega läuft mit
5V leitungen werden aber mit einem Spannugnteiler runter gebracht.

                ______
sd |-----------[ 470 ohm]--------- Atmega(5V)
            |   --------
            |
            |
            _
           | | 620ohm
           | |
           | |
           | |
           |_|
            |
            |
          ___ GND
           _
            _

von jvogel (Gast)


Lesenswert?

Also Spannung hab ich mit dem Multimeter nachgemesse, kann es sein, dass 
die 2,7V doch noch etwas zu wenig für die SD(Microsd) karte sind?

von Daniel R. (zerrome)


Lesenswert?

Moin, bei irgend einem cmd an die Karte kann man als Parameter die 
Spannung mit angeben. Die Karte antwortet dann positiv oder nicht. Weiß 
aber grad nicht aus dem Kopf welches cmd das ist.
3,3 Volt wäre schon besser und erwarte nicht zu viel von den 
Spannungsteilern.

@ Sven S. (schwerminator)
Probier mal 1k Widerstände längst den Leitungen, quasi als Terminator...
Was sagt denn das Datenblatt vom MAX3002 zu korrekten Beschaltung?


Viele Grüße

Daniel

von jvogel (Gast)


Lesenswert?

Ok dan kram ich mal lieber in meiner kiste irgendwo hab ich noch ein 
Spannungsregler au 3V, oder ich bau mir einen Spannungseiler der mit ca 
3.3V gibt. Was denkt ihr ist die bessere Wahl?

von JVOGEL (Gast)


Lesenswert?

aber der timer ist richtig eingestellt oder?

von JVOGEL (Gast)


Lesenswert?

Hat das jemand von euch mit soft SPI am laufen?

von Kurt B. (kurt)


Angehängte Dateien:

Lesenswert?

Daniel R. schrieb:
> In Chans Lib wird die zweite Fat auch nicht beschrieben, da hast Du das
> gleiche Problem.

HELLO1.TXT wurde mit Chans Lib erstellt. TEST1.TXT mit deiner, Daniel.
Danach habe ich die Karte auf Fehler prüfen lassen. Wie man sieht ist 
HELLO1.TXT unverändert, TEST1.TXT ist genau um 4kB gewachsen.

Daher würde ich vermuten das irgendeine Variable falsch initialisiert 
wird oder falsch abgefragt, <,>,<=,>=...

Das Problem ist mir schon in früheren Versionen vor der 0.6.2 
aufgefallen.

Mfg,
Kurt

von marvin (Gast)


Lesenswert?

Hallo ich habe das gleiche problem wie jvogel. Auch an einem atmega32 
ich habe ihn auf 3.3v laufen und den timer von ihm kopiert ist der timer 
falsch?  Und oder geht nur. Soft spi nicht? Sry schreibe vom handy aus 
dh vielleicht buchstaben drwher etc

von Daniel R. (zerrome)


Lesenswert?

Hallo.

@ Kurt Bohnen (kurt)
Tatsächlich, glaube es gibt da ein Problem in der Fat.
Es wird ein Cluster zu viel verkettet. Was erstmal an den Daten nichts 
ändert, da die Dateilänge ja stimmt. Es wird aber Platz verschenkt.
Bin das gerade am ändern.

@ marvin (Gast)
Welche Werte nimmst Du denn?

Viele Grüße

Daniel

von JVOGEL (Gast)


Lesenswert?

bei mir hat er probleme mit
1
loop_until_bit_is_set(SPSR,SPIF);

hab jetzt auch mal hardware SPI getestet, bitte hilft mir wer

von Daniel R. (zerrome)


Lesenswert?

@ JVOGEL (Gast)
Ich würde sagen Dein SPI läuft nicht richtig.

Um den von Kurt Bohnen (kurt) angesprochenen Bug zu beheben, müssen 
folgende Zeilen in der Datei file.c in der Funktion fflushFileData() 
ausgetauscht werden:
1
// cluster chain verketten
2
fat_setClusterChain(fat_secToClust(chain.startSectors),fat_secToClust(file.currentSectorNr));  // verketten der geschriebenen cluster

durch
1
    // cluster chain verketten.
2
    if(file.cntOfBytes == 0){                // gerade genau irgend einen sektor voll geschrieben.file.currentSectorNr zeigt jetzt auf den neu zu beschreibenden.
3
      if( file.currentSectorNr-1 >= chain.startSectors ){
4
        fat_setClusterChain(fat_secToClust(chain.startSectors),fat_secToClust(file.currentSectorNr-1));  // verketten der geschriebenen cluster
5
      }
6
    }
7
    else fat_setClusterChain( fat_secToClust(chain.startSectors),fat_secToClust(file.currentSectorNr) );

Vielen Dank für den Hinweis und viele Grüße

Daniel

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Da ich mich irgendwie nicht mehr beim SVN anmelden kann um die neue 
Version hochzuladen, poste ich die erstmal hier...

von Kurt B. (kurt)


Lesenswert?

Vielen Dank Daniel, jetzt läuft es perfekt! Allerdings hast du vergessen 
das ACMD41 von (0x80+41) auf (41) zu ändern.

@JVOGEL,
hast du einen PullUP an MISO? Auch der /SS des µC braucht einen Pullup, 
oder muss auf Ausgang geschaltet werden.

Mfg,
Kurt

von jvogel (Gast)


Lesenswert?

Hi, danke schonmal für die Tipps. Hatte gestern keine Zeit mehr zu 
testen und heute bin ich erst einmal auf der arbeit. Meinst du einen 
Pullup in form des internen oder ein externen Pullup? Wenn er nicht 
schon in der Programmierung eingebunden ist dann eher nicht, aber ich 
kann auch mal ein Foto meiner Schaltung machen, heute Abend. Der halbe 
Sonntag hab ich damit verbracht, leider bisher ohne Erfolg.

Habe ja einen spannungteiler mit 470ohm / 620 Ohm ist wirkt der nicht 
wie ein Pullup?

Bin erstma ein Kaffee trinken ;)

von jvogel (Gast)


Lesenswert?

Habe mir gestern in die Methode spi_write_command? oder so ähnlich ein 
puts("test"); rein gemacht und das ergebnis war dann ungefähr:

Boot test test

also bleibt er beim 2. mal dort hängen bei
1
loop_until_bit_is_set(SPSR,SPIF);

von Daniel R. (zerrome)


Lesenswert?

Hallo,
also nimm diese Version: 
http://www.mikrocontroller.net/attachment/105372/mmc-0.6.3.zip

Da musst Du aber noch in der mmc.c oben bei den defines folgendes 
ändern, weil ich das verpeilt hab:
1
#define  ACMD41  (0x80+41)
auf
1
#define  ACMD41  (41)

So, dann solltest Du zum testen auf jeden Fall erstmal hardware SPI 
benutzen. Bei deinem Spannungsteiler komm ich nur auf 2,844 Volt. Das 
ist bisschen wenig. Und eigentlich generell mist, dass mit dem 
Spannungsteiler!
Betreibe die Schaltung am besten mit 3,3 Volt. Was genau spricht bei Dir 
dagegen?

Zum berechnen der nötigen Timer Werte benutze ich immer folgendes Tool:
http://clsql.med-info.com/download.html
Wie sehen Deine Timer Werte aus?

Bild von der Schaltung wäre gut.

Ich bin mir sicher, dass wir das ans laufen bekommen :)

Viele Grüße

Daniel

von jvogel (Gast)


Lesenswert?

Hatte zuletzt einen spannungsteiler mit 290 ohm / 620 Ohm.

Das problem, dass ich habe ist das mein MAX232 mit 3.3V nicht so richtig 
funktionieren möchte, manchmal liest man, dass er mit 3.3V laufen würde 
aber bei mir leider nicht. Mein LCD Display funktioniert leider auch nur 
mit 5V.

Aber zum testen baue ich mir nachher eine LED auf mein Breadboard um den 
Status anzeigen zu lassen, dann kann ich auch 3.3V verwenden.

Ich hoffe, dass ich heute abend Zeit finde, dann bauch ich mir die 
Schaltung nochmal neu auf (Ohne Spannungsteiler)und mache dann ein Foto 
falls es, dann immer noch nicht geht. Und meinen Sourcecode hänge ich 
dann auch nochmal komplett an.

Vielen dank schonmal im vorraus.

von Daniel R. (zerrome)


Lesenswert?

Ok, dann mach lieber einen Spannungsteiler beim max232 um auf 3,3 Volt 
zu kommen. LCD Displays brauchen nur an der Versorgungsspannung 5 Volt. 
Zu mindest die die ich habe. Beim max232 würde dann sogar nur der RX 
Pfad zum Kontroller als Spannungsteiler reichen. Da TX ja 3,3 Volt wäre 
und das als Hi Pegel reicht...

>Breadboard

Damit hatte ich auch immer Probleme wenn es um SD Karten ging. Extrem 
kurze Kabel und Kontroller 3,3 Volt und SD Karte 3,3 Volt helfen da 
aber.

Mann muss da bedenken, dass die Karten mit 25 MHz spezifiziert sind, da 
sind saubere Flanken ein muss!

Also zusammenfassend.

Kontroller 3,3 Volt
SD/MMC 3,3 Volt
LCD 5 Volt Versorgung und 3,3 Volt Datenleitungen
MAX232 <- TX Kontroller direkt
       -> RX Kontroller Spannungsteiler auf 3 Volt

Viele Grüße

Daniel

von jvogel (Gast)


Lesenswert?

Hatte mich verschrieben, MAX323 habe ich.

von Daniel R. (zerrome)


Lesenswert?

Hm, ok mal doch mal nen kompletten Schaltplan, ich kann mir grad die 
ganze Schaltung nur schwer vorstellen.

Zu MAX323 find ich nur "Precision, Single-Supply, SPST Analog Switches" 
?

von JVOGEL (Gast)



Lesenswert?

So hab mich doppelt vertan, hab den MAx232 der funktioniert aber leider 
nicht bei 3.3v bei mir.

So hab jetzt bilder gemacht, und alles :(
vielleicht kann mir wer den helfenden schlag auf den hinterkopf geben.

von JVOGEL (Gast)


Lesenswert?

Das mit der LED an PORTA vergessen :D da war ich betrunken oder so

von Daniel R. (zerrome)


Lesenswert?

Ok, das 2. Bild ist der Max232?

Ich sehe garkeine Pegelwandlung zwischen uC und SD Karte?
Läuft da alles mit 3,3 Volt?

Toll das Bild vom Multimeter :)
Wo geht das Kabel hin?!?

Ist das da ein ISP Programmier Adapter?
Den machst Du aber nach dem Programmieren immer ab oder?

Bei Deinen Test würde ich Dir empfehlen diese Einstellung in der 
mmc_config.h noch zu machen.
1
#define MMC_MAX_SPEED FALSE


Viele Grüße

Daniel

von jvogel (Gast)


Lesenswert?

Ja im 2. Bild ist der Max232,

Multimeter kabel gehen  an das Breadboard aussen an jeweils ein stift in 
+ und GND.

Der ISP Programmieradapter ist ein USB <--> ISR Programmier adapter der 
gibt der schaltung den 5V Saft, oder bene 3,3V jenachdem was man dort 
mit einem Schalter einstellt.
Der bleibt eigentlich immer dran, oder ist das schon das problem, dass 
das SPI dadurch gestörrt wird? Bzw vom ISP Programmierer als Master 
verwendet wird? :)

von Daniel R. (zerrome)


Lesenswert?

Ja der Programmier Adapter könnte schon das Problem sein.

von JVOGEL (Gast)


Lesenswert?

So hab nun zwei dräht in den ISP programmer gesteckt fuer VCC und GND 
aber funtkioniert trozdem nicht und der MAX232 geht auch immer noch nit 
mti 3.3v :(
 manno

von Daniel R. (zerrome)


Lesenswert?

Ok, ich weiß nicht genau wo ich anfangen soll...

1. Nimm einen anständigen 3,3 Volt Regler der 1 A Strom liefert.
2. Nimm eine Anständige Quelle die den Regler speist!
3. Klemm nur die SD Karte an die SPI Schnittstelle.
4. Überprüfe alle Anschlüsse und Einstellungen im Code 3 mal!

Zu dem Max232 hatte ich Dir schonmal was geschrieben,
5 Volt Versorgung und dann an die RX TTL Seite einen Spannungsteiler!
Weißt Du was ich damit meine?

Du solltest Dir Methoden überlegen wie Du Hardware debuggst.
Mein Vorschlag: Modul weise Prüfen ob es geht und dann nach und nach 
zusammenschalten...





@ Sven S. (schwerminator)
Bist Du weiter gekommen mit diesen seltsamen Spikes da?



Viele Grüße

Daniel

von JVOGEL (Gast)


Lesenswert?

IN AVR Studio hab ich:

Device: atmega32
Frequency: 16000000
OPTIMIZATION:-O2


Ok dann muss ich warten bis ich eirder zum gelben C komme. Hab hier nur 
noch einen 3v Regler und einen 5v. Ein Stabilisiertes Netzteil hab ich 
noch und eine passende buchse dazu.
So kann ich dann auch die verschiedenen Komponente mit 5v oder 3,3v 
gleichzeitig speisen.

von JVOGEL (Gast)


Lesenswert?

@Daniel R.
ja zwischen RXD und R1 out einen spannugnteiler, damit der Atmega kein 
5v High signal bekommt, weil er mit 3.3v läuft.

von Daniel R. (zerrome)


Lesenswert?

Hm, 3 Volt sollte auch gehen. Hauptsache ein richtiger Regler.
So eine SD Karte zieht auch schon mal gerne 200 mA oder mehr kurzzeitig.

Ich hab gerade keine Lust die Pinbelegung vom Max232 nachzuschauen, aber 
ja so meinte ich das. Zwischen Max232 RX und Kontroller RX den 
Spanungsteiler

Mit Einstellungen im Code meinte ich die Pin Einstellungen falls Du sie 
geändert hast, halt sonst noch alle Änderungen im Code. Dann alle Kabel 
Verbindungen usw...


Viele Grüße

Daniel

von JVOGEL (Gast)


Lesenswert?

Ok ich tüfftel das mal die Tage zusammen und melde mich dan nochmal,

1000x Dank schonmal

von JVOGEL (Gast)


Lesenswert?

Ich glaub ich hat nen kurzen und entweder der MAX232 oder der RS232 port 
an meine PC hats durchgeknallt, naja ich lass es jetzt erstmal bis ich 
mal wieder ruhige minuten habe die tage.

von Dome k. (jvogel)


Lesenswert?

Also ergebnis bisher:

MAX232 kann nicht defekt sein, da ich einen neuen Ausgetauscht habe und 
der funktioniert auch nicht.

Atmega32 ist auch nicht defekt, habe ich auch ausgetauscht.

Weiss einer wie ich schnell einfach testen kann ob der RS232 port am pc 
nen knacks bekommen hat?

von Daniel R. (zerrome)


Lesenswert?

RX und TX brücken, dann solltest Du genau das empfangen was Du sendest.

von Dome k. (jvogel)


Lesenswert?

Ok, test Negativ. Ich glaub meine RS232 ist match...

von Buzzwang (Gast)


Lesenswert?

Momentan probiere ich die neuste LIB(0.6.3) aus.
Ich bin von der 0.6.1 umgestiegen

2 Sachen waren zu beachten:
 - Im Dateinamen muss nun ein Punkt sein (8.3). LFN ist bei mir aus
 - Das Chip_select Define ist rausgeflogen und die Pin-Belegung war 
dadurch falsch.

Übersetzen mit
  #define MMC_MULTI_BLOCK   TRUE
ging nicht.

von Matze N. (hupe123)


Lesenswert?

> 2 Sachen waren zu beachten:
>  - Im Dateinamen muss nun ein Punkt sein (8.3). LFN ist bei mir aus
>  - Das Chip_select Define ist rausgeflogen und die Pin-Belegung war
> dadurch falsch.


Kannste dazu mal etwas mehr schreiben?
-> in der Vorlage "main_simple.c" ist doch im dateinamen ein "."
-> wie hast du das Problem mit dem MMC_CHIP_SELECT gelöst. Is mir eben 
auch erst aufgefallen. Umgelötet oder einfach die Pinnummer geändert?

Grüße,
Matze

von Matze N. (hupe123)


Lesenswert?

So, habs dann auch zum laufen bekommen und kann meine Fragen jetzt für 
alle beantworten:

-> Beim Dateinamen nuss nichts geändert werden (zumindest beim 
AVR-Studio 4 und 5beta)
-> Die SD-Karte wird kompett (und nich wie im Wiki angegeben) an den 
SPI-Port angeschlossen. Falls aus einer älteren Version die Leitung vom 
CS der Karte an einen anderen PIN als den SS geht, dann muss das 
geändert werden...

Grüße,
Matze

von Matze N. (hupe123)


Angehängte Dateien:

Lesenswert?

Hi,
ich hab da nen Problem. Ich würde gerne Verzeichnisse anlegen und in 
dieses Verzeichnis eine Datei.
Wenn ich die Datei ohne Verzeichnis anlegen lasse, dann funzt alles! 
Wenn ich allerdings erst das Verzeichnis anlege und das öffne um darin 
dann die Datei zu platieren, dann bekomme ich nur Datenmüll.

Hier der Code, mit dem ich das Verzeichnis anlege und hinein wechsel:
1
  unsigned char datum_verzeichnis[] = "12345678";      
2
  ffmkdir(datum_verzeichnis);
3
  ffcd(datum_verzeichnis);
4
  _delay_ms(10);
(Die Pause an Ende nahm ich mit rein, da ich dachte, daß mein µC (ein 
ATmega128) versucht die Datei anzulegen bevor das Anlegen des 
Verzeichnisses abgeschlossen ist (-> Datendurcheinander).

Der Screenshot von dem, was mir WindowsXP SP3 anzeigt, wenn ich die SD- 
Karte einlege, is im Anhang.

Kann sich das jemand erklären?!
Ohja: Wie erwähnt: PC: Win XP SP3, µC: ATmega128, 3,3V, SD ohne Zusatz 
an SPI, Compiler AVR Studio

Grüße,
Matze

von Daniel R. (zerrome)


Lesenswert?

Hm, schau ich mir heute Abend mal an.
Möglicherweise ist da was durcheinander gekommen bei den 
Versionsänderungen.
Mag ich jetzt mal nicht ausschließen.

Viele Grüße

Daniel

von Matze N. (hupe123)


Lesenswert?

Hi,

Ich würde gerne das Einfügen von Daten in eine Datei in deine Funktion 
implementieren.
Mit Einfügen meine ich:
z.B. aus einer TXT Datei mit dem Inhalt: "Hallo Welt!" Durch einfügen 
von "schöne, neue " an die Stelle 6 "Hallo schöne, neue Welt°" zu 
machen.

Ich habe mir gestern darüber gedanken gemacht und würde dir die gern 
kurz vorstellen, damit du mir ein paar Tipps geben kannst, was ich 
möglicherweise vergessen habe:

1) mit ffseek(x); zu der einzufügenen Stelle springen.
2) mit der Bedingung ("512 - file.cntOfBytes" aus z.B. ffseek() ) die 
restlichen Bytes aus dem Sektor in einer Variablen zwischenparken damit 
sie nich überschrieben werden
3) in einer Variablen die "Nummer" des Folgesektors merken
4) normales Schreiben der einzufügenen Daten (hier "schöne, neue ")
5) zurückschreiben der Daten aus 2)
6) in der Fat Tabelle die Folgesektornummer von 3) angeben, um das alles 
auch wieder schön zu verknüpfen

Das klingt ja erstmal gar nicht schwer. Jedoch weiß ich noch nicht mit 
welches Funktionen ich die aktuelle Sektornummer und die 
Folgesektornummer auslesen kann.
Zudem weiß ich noch nicht, wie ich die Fat-Tabelle aktuallisieren soll:
macht es Sinn die gesamte Tabelle auch in einer Var. zu parken (vgl. 2) 
) um dann normal schreiben zu können. Nebenbei merke ich mir, wieviele 
Einträge ich in die Fat Tabelle mache und schreibe den Inhalt aus Fat- 
Variablen dann einfach wieder an die richtige Stelle zurück? Aber wie 
kann ich in der Fat-Tabelle schreiben?

Du siehst, noch ein paar Fragen, aber eigentlich müsste das doch möglich 
sein, oder?!

Grüße,
Matze

von Daniel R. (zerrome)


Lesenswert?

Hm, diese Diskussion hatten wir da schon mal : 
Beitrag "Re: MMC SD library FAT16 FAT32 read write"

Ich bin zu dem Schluss gekommen,dass es nicht so ohne weiteres möglich 
ist, weil man entweder immer ganze Cluster einfügen müsste. Oder man 
muss die kompletten Daten nach den eingefügten "aufrücken".

Keine Ahnung wie ein Betriebssystem das macht. Wenn ich da in eine 2 GB 
große Datei was einfüge, werden sicher nicht alle Daten umkopiert, oder 
doch?!?

Viele Grüße

Daniel

von Matze N. (hupe123)


Lesenswert?

Aber ein Sektor muss doch nicht zu 100% voll mit Daten besetzt sein. Von 
daher müsste das doch gehen. Das einzige, was ein bißchen aufwendig 
werden könnte, wäre das erneuern der FAT- Tabelle.

Ich werde das mal angehen, wenn ich etwas zeit habe. Aber kannst du mir 
noch kurz sagen, wie ich die Fat- Tabelle auslese, Daten hineinschreibe, 
usw.?

Grüße

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ich hab da im Wiki ein wenig zu geschrieben.
Falls Du danach noch Fragen hast, stell sie :)


Nur der letzte Cluster einer Fat Kette muss nicht voll besetzt sein. 
Alle anderen davor schon. Man kann also nicht einfach einen halb vollen 
Cluster mitten in die Kette schummeln...

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Hallo,
es gab tatsächlich einen Bug in ffmkdir...

Als Anhang die gefixte Version.

Als Beispiel
1
ffmkdir("Ordner     ");
2
ffcd("Ordner     ");

Viele Grüße

Daniel

von Michael Z. (incunabulum)


Lesenswert?

Daniel,

magst du bei Gelegenheit die aktuellen Versionen wieder per SVN 
verfügbar machen?

Ansonsten kommt man per deinem zugehörigen Artikel und dem dort 
gegebenen Link auf aktuelle Versionen nur bis zur Version 0.6.1. Auch 
habe ich ein bisschen die Übersicht verloren, welche Verison mit welchen 
händischen Ändeurngen nun aktuell sein könnte...

Danke, Michael

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ich kann mich nicht mehr anmelden beim SVN.

Hab dem zuständigen schon mal ne Mail geschrieben, ist aber keine 
Antwort gekommen...

Werde wohl wieder dazu über gehen die aktuellste Version im Wiki zu 
verlinken.

Viele Grüße

Daniel

von Michael Z. (incunabulum)


Lesenswert?

Daniel,

einen Link auf die aktuelle Version (wo auch immer) wär schön... svn 
noch besser. Aber was nicht ist, ist nicht :-)

Michael

von Daniel R. (zerrome)


Lesenswert?

Hi,
ja da wo es im Wiki immer den SVN Link gab, gibt es jetzt immer einen 
Link zur aktuellen Version ohne SVN.

http://www.mikrocontroller.net/articles/AVR_FAT32#Der_Status

Falls man da noch händisch etwas ändern muss schreibe ich es dann da 
auch dazu.

Viele Grüße

Daniel

von Hanno W. (hannow)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe folgendes Problem mit der Bibliothek (SourceCodeV3.0).
Mit dem µC kann ich eine Datei auf der SD Karte erstellen und auslesen, 
der Computer (WinXp ServicePack 3) kommt damit auch prima klar. Wenn ich 
allerdings mit dem Computer z.B. eine Textdatei "hallo.txt" auf der SD 
Karte erstelle erkennt der µC diese einfach nicht. Er legt die gleiche 
Datei mit dem selben Namen nochmal an, sodass diese dann zweimal 
vorhanden ist, jedoch ohne brauchbahren Inhalt. Ich habe die Karte unter 
Windows mit FAT formatiert, könnt da das Problem liegen?
Zur bessern Fehlersuche habe ich mal die "config.h", "mmc.h" und 
"SDCardTest.c" angehängt. Ich hoffe ihr könnt mir helfen.

Gruß
Hanno

von Daniel R. (zerrome)


Lesenswert?

Hallo,
nim die neuste Version. Dann ist das Problem behoben.

Viele Grüße

Daniel

von Matze N. (hupe123)


Lesenswert?

Hi, ich glaube ich habe grad wieder nen Bug gefunden...

Er ist reproduzierbar mit der Version 0.6.3.1 auf einem ATmega128 und 
beliebigen SD-Karten.
Er tritt immer auf, wenn man z.B. zwei Dateien immer abwechselnd 
beschreibt. Wenn die erste Datei größer ist als 2 Sektoren (bei 4.096 
Byte / Sektor) und sobald die zweite Datei größer wird als 2 Sektoren, 
hängt sich das Programm auf. Das funktioniert auch mit einem geänderten 
main_sample.c (nicht nur bei meinem "Mutter"- Programm)

Ich hoffe, daß das Problem kein großes ist!

Grüße und schöne Ostern noch!

von Matze N. (hupe123)


Lesenswert?

Sorry, das Problem tritt aus, wenn 4 Dateien geschrieben werden und wenn 
eine zweite größer als 2 Sektoren werden "will"
-> Sprich, wenn zwei Dateien die größe von zwei Sektoren haben und eine 
davon drei Sektoren großer werden "will" / muss.

Grüße,
Matze

von Daniel R. (zerrome)


Lesenswert?

Hallo,
poste mal den Code.

Viele Grüße

Daniel

von Hanno W. (hannow)


Lesenswert?

Hallo,
kann mir mal jemand sagen, wie ich die neue Bibliothek in mein Eclipse 
Projekt integrieren kann? Hab noch nicht so viel Erfahrung damit.
Bei der letzten Version die ich hatte, habe ich einfach die Dateien in 
mein Projekt kopiert und die Pfade zu den Header Dateien angepasst.
Jetzt habe ich mir die Version 0.6.3.1 runtergeladen und weiß eigentilch 
garnicht was ich mit den Dateien anfangen soll?

von Matze N. (hupe123)


Lesenswert?

Matze Niemand schrieb:
> Sorry, das Problem tritt aus, wenn 4 Dateien geschrieben werden und wenn
> eine zweite größer als 2 Sektoren werden "will"
> -> Sprich, wenn zwei Dateien die größe von zwei Sektoren haben und eine
> davon drei Sektoren großer werden "will" / muss.
>
> Grüße,
> Matze

Sorry, war wohl ein Fehler des Programmieres hüstel
geht alles...

Grüße,
Matze

von Daniel R. (zerrome)


Lesenswert?

Hallo.

@ Matze Niemand (hupe123)
Schön das es jetzt geht :)

@ Hanno Winter (hannow)
Ich habe im Wiki ein paar Sätze dazu geschrieben wie man das einbindet. 
Orientier Dich einfach an den mitgelieferten Beispielen. Oder an den 
Beispielen früherer Versionen.

Viele Grüße

Daniel

von Matze N. (hupe123)


Angehängte Dateien:

Lesenswert?

Hi,

ich wollte grad die Version 0.6.3.1 in meine Anwendung einbauen und 
bekomme, auch beim Compilieren der main_sample, haufenweise 
Fehlermeldungen (siehe Anhang).

Wo kommen wie auf einmal her? Ich finde den "wahrscheinlich" einfach 
Fehler nich...

Der Compiler is: AVR Studio 4 und 5beta (beide die gleichen 
Fehlermeldungen, im Anhang sind die aus AVR Studio 5beta), WinXP SP3

Grüße, Matze

von Daniel R. (zerrome)


Lesenswert?

Du versuchst die Version für den STM32 zu kompilieren...

von Matze N. (hupe123)


Lesenswert?

??? Hä? Ich habe die Datei eben nochmal von 
http://www.mikrocontroller.net/articles/AVR_FAT32#Der_Status 
heruntergeladen und aus dem Ordner "AVRStudio-SD.MMC_lib_0.6.2" die 
Datei "mmc_project.aps" geöffnet und wollte die compilieren - das selbe 
Problem. Und wenn ich AVR studio 4 frage, welcher µC benutzt werden 
soll, steht da "ATmega168"...
Was mache ich falsch?

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Äh ja sorry, da ist die falsche mmc.c rein gerutscht...
Muss das neu packen.

Als Anhang mal eine mmc.c die funktionieren sollt.

Viele Grüße

Daniel

von Matze N. (hupe123)


Lesenswert?

Jo, danke!! Und einen schönen Tag dir!

von Matze N. (hupe123)


Lesenswert?

Hmm,... ich wollte eben mal wieder weitermachen und AVRstudio4 schmeißt 
mir mit der neuen mmc.c Datei immernoch ein Fehler raus:
1
../fat.c:213: warning: implicit declaration of function 'toupper'

Grüße,
Matze

von Daniel R. (zerrome)


Lesenswert?

Hallo,
das ist ja nur ein warning.
Eigentlich sollte auch das AVR Studio diese Funktion kennen...

Viele Grüße

Daniel

von Hanno W. (hannow)


Lesenswert?

Hallo,
ich brauche mal wieder einen Tipp...seit dem ich nun die neue Bib auf 
den Controller gespielt habe, funktioniert die Initialisierung einfach 
nicht?
Ich denke, dass ich alles so wie vorher eingestellt habe, also liegt 
Chip Select noch auf PB1,...normal wäre PB4, aber wenn ich das in der 
mmc.h anpasse müsste es ja eigentlich gehn?
Ich weiß gerad gar nicht wo ich anfangen soll zu suchen...an der 
Hardware kanns nicht liegen, denn mit der alten Version klappt die 
initialisierung ohne Probleme.

von Daniel R. (zerrome)


Lesenswert?

Hallo,
hast Du einen Pullup an DO der Karte, bzw am MISO vom Kontroller?
Und ja, der Chip Select Pin hat sich geändert, also die Belegung. Wenn 
Du das in der mmc.h anpasst sollte das gehen.

Viele Grüße

Daniel

von E. L. (robo-man)


Lesenswert?

Hallo!
Das ist eine echt geile Lib. Super Arbeit!
Auch für Einsteiger leicht verständlich.
Kann mir einer vielleicht sagen, wie ich mit dieser Lib z.B. MP3 Dateien 
einfach nach der Reihe auslesen kann, ohne dass ich den Namen angeben 
muss?
Das z.B. 10 mp3´s auf der sd karte sind und der µc die dann alle 
nacheinander ausliest. Ist das möglich?
Danke!!!

von Marcel (Gast)


Lesenswert?

hi

@ Matze Niemand

"Hmm,... ich wollte eben mal wieder weitermachen und AVRstudio4 schmeißt
mir mit der neuen mmc.c Datei immernoch ein Fehler raus:

../fat.c:213: warning: implicit declaration of function 'toupper'"

du musst die Datei ctype.h in fat.c einbinden dann geht`s
#include <ctype.h>


mfg Marcel

von Hanno W. (hannow)


Lesenswert?

Hallo,

ich habe die neue Bibliothek bei mir immer noch nicht zum laufen 
gebracht...hatte zwar keinen Pullup an DO, aber selbst mit klappt die 
Initialisierung nicht.

Mein Problem mit der alten Bib ist ja nur, dass ich mit dem Computer 
keine Dateien auf der SD-Karte erstellen kann, um diese dann mit dem 
Mikrocontroller weiterzuverarbeiten. Kann mir jemand sagen, was der 
Computer anders bei der Erstellung von Dateien macht als der 
Mikrocontroller?

von Daniel R. (zerrome)


Lesenswert?

Hallo,
wo in der Initialisierung bleibt es denn hängen?

Viele Grüße

Daniel

von Hanno W. (hannow)


Lesenswert?

Hallo,
das weiß ich leider nicht, habe keine Möglichkeit das Programm zu 
debuggen...

von Daniel R. (zerrome)


Lesenswert?

Doch, das hat man immer...mit ein wenig Kreativität :)

Mach eine LED mit Vorwiderstand an einen Pin.
Im Programm machst Du die LED dann an einer bestimmten Stelle an. 
Entweder das Programm läuft bis da und die LED leuchtet, oder eben 
nicht. So kann man sehen bis wo es läuft.
Du könntest Dir natürlich auch Debug Ausgaben auf dem uart machen oder 
so...

Viele Grüße

Daniel

von holger (Gast)


Lesenswert?

Wieso ist in der 0.6.3.1 beim AVR STM32 Code drin?

von Daniel R. (zerrome)


Lesenswert?

Weil ich es verpeilt habe.
Versuche am Wochenende mal ein neues Paket zu machen, sorry.

Viele Grüße

Daniel

von Flo W. (Firma: privat) (florian1x)


Lesenswert?

Hallo,

habe da mal ein paar Fragen zur lib:

Ist das Low-Level IO (also MMC/SD etc.) vom fat code getrennt?
Weil ich dies selber realisiert habe und das gerne so übernehmen würde.

unter welcher Lizenz läuft der Code? Weil ich derzeit an einem Projekt 
sitze, was unter Umständen kommerziell eingesetzt werden soll.


mit freundlichen Grüßen
Flo

von Daniel R. (zerrome)


Lesenswert?

Hallo,
getrennt ist relativ :)

War mal so gedacht, ist aber dann doch relativ verzahnt.
Klar schreiben eines Blocks und Initialisierung sollte ohne weiteres 
portierbar sein.

Lizenz ist mir egal.

Viele Grüße

Daniel

von Flo W. (Firma: privat) (florian1x)


Lesenswert?

Ok, danke für die zügige Antwort, ich schau mal gerade ob ich das 
hinkriege mit dem trennen.

von Sven Meier (Gast)


Lesenswert?

Ist es gestattet diese lib in einem Komerziellen Projekt zu verwenden ?



Gruß Sven Meier

von Sven Meier (Gast)


Lesenswert?

Frage hat sich erledigt

von Daniel R. (zerrome)


Lesenswert?

Hallo,
da das jetzt schon mehrer Leute gefragt haben,
was würde passieren wenn ich sage:" Nee gib mir mal 50 Euro dafür"?

Mir ist es aber egal was wer damit macht...


Viele Grüße

Daniel

von Flo W. (Firma: privat) (florian1x)


Lesenswert?

Mach ne readme.txt mit dazu
wo du nen copyright mit deinem namen reinschreibst
und dadrunter dass es BSD is. Dann kann die jeder Frei verwenden 
bearbeiten und sons was

ein zwei regeln gibt es da noch aber prinzipiel sollte die Linzenz für 
das projekt hier ganz gut sein :P

von Gedankenmacher (Gast)


Lesenswert?

>da das jetzt schon mehrer Leute gefragt haben,
>was würde passieren wenn ich sage:" Nee gib mir mal 50 Euro dafür"?

wahrscheinlich wärst du dann Händler mit allem drum und dran. Steuer, 
Gewährleistung, Support, irgendwelche Anmeldungen, ...

btw. tolle Bibliothek.

von holger (Gast)


Lesenswert?

>btw. tolle Bibliothek.

Ja, wirklich toll. Der STM32 Schrott steht seit dem
31.05.2011 immer noch im AVR Teil.

von Daniel R. (zerrome)


Lesenswert?

Kommendes Wochenende änder ich das, versprochen...

von abccba (Gast)


Lesenswert?

Hallo,

ich habe eine kleine, wahrscheinlich banale Frage. Habe eine SD Karte 
mit einem Mega 16 verbunden und möchte Werte aus einer Text-Datei 
auslesen und an einem Port ausgeben. Als nur komisches Zeug ausgegeben 
wurde habe ich mal per uart ausgeben lassen, was genau der uC eigentlich 
von der Karte einliest und musste feststellen dass da irgendein Murks 
angezeigt wird. Also habe ich zunächst eine Text-Datei mit ffwrite vom 
uC aus erstellt und diese dann anschließend wie vorher ausgegeben... das 
funktionierte einwandfrei. Wenn ich jedoch nur ein einziges Zeichen mit 
einem Text-Editor in der Datei am Rechner verändere und das ganze 
speichere, dann steht wieder nur murks da. Woran liegt das? Ich habe die 
Vermutung dass irgendwas mit der Codierung nicht stimmt, bzw der Editor 
da irgendwie noch was reinmogelt. Wie kann man nun am PC eine Text-Datei 
erstellen, die auch wirklich nur aus dem besteht was man im Editor 
sieht?

Viele Grüße

PS.: die Library ist echt super!

von Daniel R. (zerrome)


Lesenswert?

Hallo,
eine ganz normale Textdatei muss die Lib lesen können. Hast Du die Lib 
mit LFN Untersützung kompiliert? Vielleicht macht der PC da immer lange 
Dateinamen aus den Dateien beim schließen. Wenn Du so eine Datei hier 
hochladen würdest, schau ich mir die mal mit einem Hex-Editor an. Der 
zeigt einem wirklich die Bytes an aus der so eine Datei besteht.

Viele Grüße

Daniel

von abccba (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Daniel,

hier hab ich mal ein paar Werte eingetragen, einmal mit dem Mac 
Text-Edit in test.txt und dann nochmal mit Windows im Editor in 
test1.txt. Die Codierung ist Standardmäßig bei Windows auf ANSI und Bei 
test.txt hab ich ASCII eingestellt, weil dort anscheinend UTF-8 Standard 
ist. Das wär echt super, wenn du dir das kurz mal anschauen könntest. 
Achso, LFN ist natürlich mitkompiliert worden.

Viele Grüße und Danke für die Hilfe

PS.: Ich hätte noch eine andere Frage zur Funktion ffls(): Wie genau 
funktioniert diese?
bzw. was beudeutet genau "// zeigt direktory inhalt an, muss zeiger auf 
eine ausgabe funktion übergeben bekommen" ? Kann ich die Funktion nutzen 
um in einen String sämtliche Dateinamen, die vorhanden sind, 
reinzukopieren? Wenn ja, wie genau stelle ich das an?

von abccba (Gast)


Lesenswert?

Oh ich seh grad das sind in beiden Fällen tatsächlich genau 15 Bytes. 
Sehr seltsam. Kann es sein dass etwas mit der Formatierung der Karte 
nicht stimmt? Bzw wie kann ich diese am besten formatieren?

von Daniel R. (zerrome)


Lesenswert?

Hallo,
am besten formatierst Du die Karte mit FAT32, windows oder linux, das 
ist egal.

ffls() ist eine Baustelle seit der Umstellung auf LFN. Das zeigt 
momentan nämlich nur SFN an.

Ich schau mir das spätestens morgen mal genauer an..

Viele Grüße

Daniel

von Daniel R. (zerrome)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,
hier mal die neu gepackte Version.
Um es mir einfacher zu machen, werde ich jetzt einfach die AVR und ARM 
Sachen getrennt hier http://www.mikrocontroller.net/articles/AVR_FAT32 
Posten.

Viele Grüße


Daniel

von SD-Card Greenhorn (Gast)


Lesenswert?

Hallo

ich habe noch keinerlei Erfahrung mit SD-Card Anwendungen. Ich möchte 
angeregt durch diesen Thread mal damit anfangen. Ich habe einen 
Atmega328P. Einige haben da ja schon die LIB angepasst, haben aber nicht 
explizit geschrieben was. Wo muß man da überall anpassen?
-mmc.h
-uart.h
..oder sonst noch wo? Ich habe im Artikel nichts über Prozessoranpassung 
gelesen. Gibt es ein "kleines" Testprogram, mit dem eine "schnelles" 
erfolgserlebnis hat.

Vielen Dank
Achim

von Daniel R. (zerrome)


Lesenswert?

Hallo,
es liegt ein Beispielprogramm bei.

Für den ATmega328 musst Du nur, wie Du schon festgestellt hast, die 
mmc.h und das Uart Zeug anpassen. Hast Du spezielle Fragen?

Viele Grüße

Daniel

von SD-Card Greenhorn (Gast)


Lesenswert?

Hallo Daniel,

vielen Dank für deine Antwort. Konkrete Fragen kommen eventuell erst 
noch....

MfG
Achim

von SD-Card Greenhorn (Gast)


Lesenswert?

Hallo

ich möchte die SD-Card an einen Atmega328P 3,3V System hängen. Meine 
Frage ist nun muß man da Pullup Widerstände dranmachen?
Ich habe in der mmc.c nichts gefunden dass da die internen Pullups 
aktiviert werden?

Es gibt ja da sehr viele Schaltungsvarianten. Kann mir jemand kurz sagen 
welche Ankopplung bei dem 3,3V System am erfogversprechendsten ist?

Vielen Dank
Achim

von Daniel R. (zerrome)


Lesenswert?

Hallo,
ja Pullup an MISO wäre ganz gut. Ordentliche Stromversorgung und 
Enstörkondensatoren Kondensatoren schaden auch nicht.

Ich hab aber auch schon Schaltungen gesehen, da hätte man gesagt, DAS 
läuft NIEMALS, hat es dann aber doch...

Viele Grüße

Daniel

von Andre I. (scuido)


Lesenswert?

Hallo,

super Lib, ein großes Dankeschön an alle die da mitgewerkelt haben.

Ich habe nun ein kleines Problem,

wenn ich eine Datei erstelle und dort mit einer Schleife 100mal das 
gleiche reinschreibe und anschließend wieder schließe, danach denn 
wieder mit dem µC auslese und über uart ausgebe, funktioniert alles 
wunderbar.
(Quelltext ist der aus dem Tutorial nur mit ner Schleife extra)

Wenn ich nun aber die SD Karte in den PC stecke findet er zwar die 
Datei, sie hat auch ne variable Größe z.B. 5kB(jenachdem wie oft ich da 
reinschreibe), nur kann ich sie nicht öffnen. Windows meint, die Datei 
sei beschädigt. Woran liegt das?


Leider bin ich gerade erst mit der SD/FAT Materie angefangen und kenne 
da noch nicht alle Vorgaben.

Viele Grüße
André

von Andre I. (scuido)


Lesenswert?

Was ich noch vergessen habe. Unter Linux kann man die Datei öffnen.

Gruß
André

von Daniel R. (zerrome)


Lesenswert?

Hallo,

probier mal nur mit kurzen Dateinamen zu kompilieren und dann das mit 
der Datei. Poste zur Sicherheit mal den Code den Du geändert hast, 
vielleicht ist da ein Fehler.
Um zu verstehen was da passiert ist es gut sich die Daten mal mit einem 
Hex-Editor wie WinHex anzuschauen. Da kann man dann genau sehen wie die 
Daten auf der Karte strukturiert sind.

Viele Grüße

Daniel

von Andre I. (scuido)


Lesenswert?

Hey, habe das Porblem gefunden.

Scheinbar war das Format der Karte nicht auf FAT16/32, sondern FAT12. 
Deine Lib hat das nicht erkannt und dachte es sei FAT16, so hat die denn 
einfach drauf geschrieben, sodass die Daten zwar drauf waren aber das 
Dateisystem kaputt war.

Mit ne größeren Karte die auf FAT32 formatiert wurde läuft es nun.


Ich hatte das gleiche Problem mit dem exacten Code von dir.

Linux ist es scheinbar völlig wurst was es bekommt, aber Windows ist da 
dummerweise etwas zimperlich... ;)

Danke aber für deine Rückmeldung, vielleicht hilft dir der Fehler ja, um 
die Lib. noch bissle robuster zu machen.

von Max (Gast)


Lesenswert?

Hallo Zusammen,

ich versuche gerade ein Verzeichnis auf der SD Karte an zu legen.
Es wir auch erzeugt, nur lässt es sich am PC nicht öffnen. Es kommt eine 
Fehlermeldung.

der Code sieht so aus.

uint8_t dada[] = "DAN";
ffmkdir(dada);

Mache ich etwas falsch?

Datei erzeugen funktioniert, öffnen schreiben, lesen alles gut.

Gruß

Max

von Daniel R. (zerrome)


Lesenswert?

Hallo,
probier mal ob dieses Beispiel funktioniert:

Beitrag "Re: MMC SD library FAT16 FAT32 read write"

Also nur die Art und Weise wie das da erstellt wird. Nicht diese Version 
von da, sondern mit der Version von hier:

http://www.mikrocontroller.net/articles/AVR_FAT32

Viele Grüße

Daniel

von Max (Gast)


Lesenswert?

Danke das war es.

Ist vielleicht an gedacht in der nächsten Version eine kleine Schleife 
im ffmkdir zu integrieren die prüft wie lang der String ist und dann 
entsprechen SPACE anhängst?

Gruß

Max

von Christian (Gast)


Lesenswert?

Hi Daniel !

Erstmal super Bibliothek.

Ich habe jetzt nicht sämtliche Antworten darauf gelesen und hoffe das 
meine folgende Frage noch nicht gestellt wurde :).


Ich möchte mittels Microblaze und dem dazugehörigen SPI Core Daten auf 
eine SD Karte schreiben und diese komfortabel via PC auslesen. Also z.B. 
Prozessdaten abgespeichert in einer .txt file.

Eignet sich deine Bibliothek für solch eine Hardware Platform?

Ich habe noch nie mit FAT16/32 gearbeitet und hoffe, dass die Frage 
nicht zu trivial ist :)

Gruss

von Daniel R. (zerrome)


Lesenswert?

Hallo,
das sollte kein Problem sein.
Habe auch die Lib auch schon auf einem Altera NIOS laufen gehabt. 
Genauer gesagt mit dem DE2 Board von Altera. Du musst nur den ganzen SPI 
Kram anpassen...

Viele Grüße

Daniel

von Christian (Gast)


Lesenswert?

Hi,

Okay danke Dir!

Werd mich evtl. nochmal melden, sofern ich noch Fragen habe :)

Gruss

von Christian F. (christianf)


Lesenswert?

Eine Frage hab ich noch,

ich war gerade drauf und dran das komplett selber zu schreiben. Also 
zuerst die Karteninitialisierung realisieren, dann schreiben eines 
Blockes und dann am "Ende" die Realisierung von FAT32.

Nun überleg ich gerade ob ich dein angebotenes Projekt verwenden, da ich 
Neuling auf dem Gebiet bin. Jedoch hab ich absolut kein Überblick über 
das, was angepasst werden muss.

Ist die Initilisierungsprozedur denn an den "initialization flow" von 
der Spezifikation angepasst ?
http://elm-chan.org/docs/mmc/sdinit.png

von Christian F. (christianf)


Lesenswert?

Kann den obigen Beitrag nichtmehr editieren (leider). Sorry also für den 
Spam.

Ich wollte Dich fragen ob es mit der TPU Probleme geben könnte.

Irgendwie verwendest du ja "TimingDelay" für die mmc_init Funktion. Ist 
das eine über die TPU vom AVR (falls vorhanden) erzeugte Verzögerung?

Wie müsste man es verändern ? Reicht da eine einfache "Soft-Tpu" in Form 
einer for-Schleife (bissle unsauber ich weiß :) ).

Gruss
Christian

von Xdim (Gast)


Lesenswert?

Hallo,
erstmal großen Dank an diese gute Library. Ich benutze sie um auf einer 
SD/SDHC eine TXTdatei anzulegen um dort meine AD gewandelten Werte 
abzuspeichern. Das funktioniert bis jetzt auch ganz gut... Nun habe ich 
Probleme bei einer anderen Sache. Ich möchte auf der SD Karte eine Datei 
(unter Windows) anlegen. Die heißt dann z.B. config.txt. Von dort soll 
sich der Controller später verschiedene Werte holen und die 
entsprechenden Variablen (also die Controllervariablen wie z.B. 
Abtastzeit) dannach setzen. Das Problem ist, dass die unter Windows 
angelegte Datei von der FATlibrary nicht gefunden wird. Ich habe es mit 
ffopen((unsigned char*)config.txt) und auch direkt mit 
if(fat_loadFileDataFromDir((unsigned char*) "config.txt")==TRUE)... 
probiert, doch leider kein Erfolg. Ich habe auch schon verschiedene 
Schreibweisen versucht (CONFIG, CONFIG  TXT, CONFIG.TXT). Hat auch nicht 
geklappt.
Funktionieren tut es nur, wenn ich mit meinem Controller die config.txt 
Datei anlege und später unter Windows editiere. Dann wird die Datei auch 
immer gefunden und ich kann die nötigen Werte raus holen.


für Tipps wäre ich sehr dankbar.

von Mark (Gast)


Lesenswert?

Hi!

Ich habe ein Problem und zwar hab ich das fertige KEIL - Project von 
Version 0.6.3.1 auf meinen STM32F107VB geworfen. Ich hab nur den CS-Pin 
auf meine Hardware angepasst.
Aber leider funktioniert bei mir das mmc_init nicht.
bei CMD0 bekomm ich noch 0x01 zurück, aber bei ACMD41 oder CMD1 bekomm 
ich immer 0xFF zurück.
Hat wer Erfahrung damit oder eine Idee was mein Problem sein könnte?
Vielen Dank schonmal...

lG
Mark

von US (Gast)


Lesenswert?

Hallo,
wollte mit folgenden Parametern die Lib übersetzen.

MMC_OVER_WRITE = FALSE
MMC_MULTI_BLOCK = TRUE


Fehlermeldung!
start_Sectors und currentSectorNr sind nicht in struct Fat_t vorhanden.

Und so wie es aussieht, hat der Compiler wohl auch noch recht.


Gruß
Uwe

von Daniel R. (zerrome)


Lesenswert?

Hallo, ja hat er.

http://www.mikrocontroller.net/articles/AVR_FAT32#Der_Status

Da steht das Multiblock ungetestet ist...

Hatte momentan sehr wenig Zeit. Wird aber kommenden Monat deutlich 
ruhiger werden.


Grüße

Daniel

von US (Gast)


Lesenswert?

Hallo,
sollte nur eine Mitteilung sein und auf keinen Fall etwas anderes.
Finde die Lib sonst sehr gut.

Danke

Gruß
Uwe

von A. G. (Firma: Conrad) (goth_conrad)


Lesenswert?

Hallo,

ich habe Ihnen eine PM geschickt, leider ohne Hinweis, ob Sie die Info 
erhalten haben. Deshalb schreibe ich zur Sicherheit hier im Thread.
Bitte kontaktieren Sie mich, sobald Sie die Nachricht erhalten.

Vielen Dank

von Steve (Gast)


Lesenswert?

Hi Leute,

Ich versuch schon seit einiger Zeit mit der ffwrite funktion die ADC 
werte meines XMega128 abzuspeichert. Strings klappen einwandfrei jedoch 
mit den int da hab ich probleme entweder er zeigt nur hieroglyphen (im 
übertragenen Sinn) an oder gar nichts an.

Ich speichere es als *.txt file.

Wahrscheinlich ist es nur eine kleinigkeit die ich übersehen hab aber 
ich weis nicht mehr weiter.

Ich hoffe Ihr wisst vielleicht was.

Übrigens danke für die tolle lib.

von Gerhard G. (xmega)


Lesenswert?

Hallo;


Steve schrieb:
> ich weis nicht mehr weiter.


int ffwrite_putchar(char c, FILE *stream); // // bindet ffwrite(c) ein


 // bindet ffwrite() ein
 static FILE my_stdout = FDEV_SETUP_STREAM(ffwrite_putchar, NULL, 
_FDEV_SETUP_WRITE);

int main(void)
{
//....
stdout = &my_stdout; // bindet printf() ein

printf("%02d; %02d; \r\n",ADCWERTxx,ADCWERTyy);// auf SD-Card speichern
//....

}

int ffwrite_putchar(char c, FILE *stream) // // bindet ffwrite() ein
{
   ffwrite(c);
  return 0;
}


bitte die nötigen Maßnahmen für printf(), float, usw. beachten

Makefile :

PRINTF_LIB = $(PRINTF_LIB_FLOAT)


Gruß xmega

von Steve (Gast)


Lesenswert?

Super danke das funktioniert einwandfrei, jedoch hab ich jetzt ein 
anderes kleines problem mit meinen dogl128 den ich verwende. Den 
beschreib ich leider auch mit der printf funktion.

Jetzt schreibe ich zwar wenn ich ins Unterprogramm springe die funktion 
um auf die sd-karte und wenn ich wieder rausspring schreib ichs wieder 
um auf den lcd. Nun geht der Display so lange aus so lang ich im 
Unterprogramm bin.

Gibt es irgendeine möglichkeit auch eine andere funktion als die printf 
zu verwenden???

von Gerhard G. (xmega)


Lesenswert?

Hallo,

du legst im Prinzip zweimal das Selbe an und wechselst nur mit

stdout = &mystdout; // bindet ffwrite() ein

oder

stdout = &my_stdout; // bindet printf() unter DOGM128 ein

Das funktioniert sehr gut, ich mach genau das Selbe.

Ich schreibe Temperaturen auf die SD-Card

z.B


stdout = &my_stdout; // bindet ffwrite()() ein


printf("%02d; %02d; \r\n",ds18b20.cel[0],ds18b20.cel[1]);// SP anzeigen

stdout = &mystdout; // bindet printf() DOGM128 ein



Gruß xmega

von Stephan K. (dustpuppy)


Lesenswert?

Hi,
kann sein, dass ich was falsch mache, aber kann auch sein, dass ich 
einen Fehler gefunden hab.
Ich habe zwei Dateien auf der Karte. Wenn ich eine dritte Datei anlege, 
in die ich die Daten einer der beiden Datein kopiere und dann die 
Quell-Datei loesche, dann wird die zweite Datei, die am Anfang da war 
gleich mit geloescht.
Das Kopieren mach ich so, dass ich eine Zeile lese, die Datei schliesse 
und die Daten dann in die Zieldatei schreibe, diese wieder schliesse und 
so weiter. Also ist immer nur eine Datei offen. fflush verwende ich auch 
nach jedem Zugriff und ich habe es bereits versucht mit Pausen zwischen 
den Zugriffen.

Gruesse

Dusty

von Daniel R. (zerrome)


Lesenswert?

Hallo,

poste doch mal den Code mit dem Du das machst.
Vielleicht kann man dann mehr dazu sagen.

Viele Grüße

Daniel

von Stephan K. (dustpuppy)


Angehängte Dateien:

Lesenswert?

Hi,
das wird jetzt nicht grade wenig.

Die Datenbank Funktionen:
1
struct _data_info_
2
{
3
  uint16_t num_fields;
4
  uint16_t num_data;
5
  char name[20][20];
6
  char DATA[20][20];
7
  char *db;
8
}DATA_INFO;
9
10
void Read_DB(uint16_t n)
11
{
12
      int count=0;
13
      int c,t;
14
      uint16_t s=0;
15
  
16
      if( MMC_FILE_OPENED == ffopen(DATA_INFO.db,'r') )
17
      {
18
  while(s<=n)
19
  {
20
    for(t=0;t<DATA_INFO.num_fields-1;t++)
21
    {
22
      count=0;
23
      c=ffread();
24
      while( (c!=',') )
25
      {
26
        tmp_buffer[count]=c;
27
        c=ffread();
28
        count++;
29
      }
30
      tmp_buffer[count]='\0';
31
      if(n==0)
32
      {
33
        sprintf(DATA_INFO.name[t],"%s",tmp_buffer);
34
      }
35
      else
36
      {
37
        sprintf(DATA_INFO.DATA[t],"%s",tmp_buffer);
38
      }
39
    }
40
    count=0;
41
    c=ffread();
42
    while( (c!='\n') )
43
    {
44
      tmp_buffer[count]=c;
45
      c=ffread();
46
      count++;
47
    }
48
    count--;
49
    tmp_buffer[count]='\0';
50
      if(n==0)
51
      {
52
        sprintf(DATA_INFO.name[t],"%s",tmp_buffer);
53
      }
54
      else
55
      {
56
        sprintf(DATA_INFO.DATA[t],"%s",tmp_buffer);
57
      }
58
    s++;
59
  }
60
  ffclose();
61
      }
62
}
63
64
void Open_DB(char *file_name)
65
{
66
  uint16_t count_fields=0;
67
  uint16_t count_data=0;
68
  int c;
69
  uint32_t seek;
70
  int fields_counted=FALSE;
71
  
72
    if( MMC_FILE_OPENED == ffopen(file_name,'r') ){
73
    seek = file.length;
74
    do{
75
      c=ffread();
76
      if( (c==',') && (fields_counted==FALSE) )
77
      {
78
        count_fields++;
79
      }
80
      if( (c=='\n') )
81
      {
82
        if(fields_counted==FALSE)
83
        {
84
          count_fields++;
85
        }
86
        count_data++;
87
        fields_counted=TRUE;
88
      }
89
    }while((--seek));
90
    ffclose();
91
  }
92
  DATA_INFO.num_fields=count_fields;
93
  DATA_INFO.num_data=count_data-1;
94
  DATA_INFO.db=file_name;
95
  Read_DB(0);
96
}
97
98
void Delete_DB(uint16_t n)
99
{
100
    int t,x;
101
    int c;
102
  
103
    if(MMC_FILE_OPENED == ffopen("temp.tmp",'c') )  // Leere Datei anlegen
104
    {
105
  fflushFileData();
106
  ffclose();
107
    }
108
    
109
    if( MMC_FILE_OPENED == ffopen("temp.tmp",'r') )  // Temporaere Datei oeffnen
110
    {
111
      for(t=0;t<DATA_INFO.num_fields-1;t++)
112
      {
113
  ffwrites(DATA_INFO.name[t]);      // Feldbezeichnung eintragen
114
  ffwrite(',');          // Komma anfuegen
115
  fflushFileData();
116
      }
117
      ffwrites(DATA_INFO.name[t]);      // Feldbezeichnung eintragen
118
      ffwrite(0x0D);          // Zeile abschliessen \n
119
      ffwrite(0x0A);          // Zeile abschliessen \r
120
      fflushFileData();
121
      ffclose();
122
    }
123
    
124
    c=DATA_INFO.num_data;
125
    
126
    for(x=1;x<n;x++)          // Datensaetze vor dem zu loeschenden durchgehen
127
    {
128
      Open_DB("loks.dat");        // Datenbank oeffnen, um die Info struct aktuell zu halten
129
      Read_DB(x);          // Datensatz holen
130
      if( MMC_FILE_OPENED == ffopen("temp.tmp",'r') )  // Temporaere Datei oeffnen
131
      {
132
  ffseek(file.length);        // Bis ans Dateiende gehen
133
  for(t=0;t<DATA_INFO.num_fields-1;t++)
134
  {
135
    ffwrites(DATA_INFO.DATA[t]);      // Datenfeld eintragen
136
    ffwrite(',');          // Komma anfuegen
137
    fflushFileData();
138
  }
139
  ffwrites(DATA_INFO.DATA[t]);      // Datenfeld eintragen
140
  ffwrite(0x0D);          // Zeile abschliessen \n
141
  ffwrite(0x0A);          // Zeile abschliessen \r
142
  fflushFileData();
143
  ffclose();
144
      }
145
    }
146
    for(x=n+1;x<=c;x++)          // Datensaetze nach dem zu loeschenden durchgehen
147
    {
148
      Open_DB("loks.dat");        // Datenbank oeffnen, um die Info struct aktuell zu halten
149
      Read_DB(x);          // Datensatz holen
150
      if( MMC_FILE_OPENED == ffopen("temp.tmp",'r') )  // Temporaere Datei oeffnen
151
      {
152
  ffseek(file.length);        // Bis ans Dateiende gehen
153
  for(t=0;t<DATA_INFO.num_fields-1;t++)
154
  {
155
    ffwrites(DATA_INFO.DATA[t]);      // Datenfeld eintragen
156
    ffwrite(',');          // Komma anfuegen
157
    fflushFileData();
158
  }
159
  ffwrites(DATA_INFO.DATA[t]);      // Datenfeld eintragen
160
  ffwrite(0x0D);          // Zeile abschliessen \n
161
  ffwrite(0x0A);          // Zeile abschliessen \r
162
  fflushFileData();
163
  ffclose();
164
      }
165
    }
166
}

Der Fehler tritt in Delete_DB auf. Die Bilder zeigen, was ich meine. Die 
Funktion ist noch nicht fertig, da ich den Fehler erst behoben haben 
muss.
Spaeter wird das orginal File geloescht und das temporaere File noch mal 
kopiert als orginal.
Was mich dann auch zum naechsten Punkt bringt. Eine Funktion zum 
Umbennen von Dateien waere echt hilfreich.

Die Bilder zeigen Folgendes. Zuerst was auf der Karte ist am Anfang. 
Dann dass das Kopieren funktioniert hat. Datensatz 3 ist geloescht in 
temp.tmp. Dann dass nicht nur das geloescht File weg ist, sondern auch 
noch eine weitere Datei fehlt.
rm im Terminal ruft nur ffrm("temp.tmp") auf.

Gruesse

Dusty

von Stephan K. (dustpuppy)


Lesenswert?

Hi again,
und noch ein Fehler. Ich habe eine Karte geloescht und eine Datei mit 
2mb Groesse angelegt. Diese habe ich mit Leerzeichen vollgeschrieben. 
Wenn ich die Datei jetzt lese, dann sind dort Frakmente alter Dateien 
drin.

Gruesse

Dusty

von Daniel R. (zerrome)


Lesenswert?

Hallo,
erstmal:

Das ist doppelt in der Kombination! ffclose ruft fflushFileData eh auf. 
Das erzeugt unnötige Schreiboperationen.
1
fflushFileData();
2
ffclose();

fflushFileData sollte nur verwendet werden wenn man ewig lange eine 
Datei geöffnet hat und sicherheitshalber zwischendurch mal die Daten 
sichern möchte. Sonst ist das nicht nötig. Im gegenteil, es werden so 
Unmengen von Schreiboperationen verursacht.

>Der Fehler tritt in Delete_DB auf.
Aber erst bei rm verschwinden doch die Dateien oder? Sind vorher alle 
Dateien da und so wie sie sein Sollten? Mit Pc überprüft?

Dann, was meinst Du mit gelöscht? Formatiert?
Wie legst Du denn eine Datei mit 2MB an schreibst erst dann?

Poste mal bitte noch die Dateien, dann schau ich mal, wann ich Zeit habe 
das bei mir laufen zu lassen um den Fehler reproduzieren zu können.
Hilfreich wäre auch die mmc_config.h und welche Version der Lib Du 
benutzt.

Viele Grüße

Daniel

von Kazs (Gast)


Lesenswert?

Hi!

Wie schaut denn der Speicherverbrauch der Lib aus (mit gehts 
hauptsächlich um RAM)? Wieviel belegt die Statisch im RAM und wieviel 
Platz solle auf dem Stack noch verfügbar sein?

von Thilo M. (Gast)


Lesenswert?

Hallo Daniel,

erst mal Kompliment für die gelungene Lib!

Banale Frage:
Ich habe die Lib in einen Datenlogger integriert, läuft so weit auch 
super (Textdatei, ca. 40 Byte pro Zeile, minütliches, zeilenweises 
Schreiben).

Das Problem ist, dass die Ansteuerung nach ca. 12h "abschmiert", die 
Karte wird dauerhaft angewählt und die Datei zerschossen.
Meine Vermutung ist, dass zwischendurch ein fat-lookup stattfinden 
sollte.
Kann das sein? Karte ist dauerhaft unter Spannung.
Und wie kann ich einen fat-lookup bei initialisierter Karte durchführen?

von Thilo M. (Gast)


Lesenswert?

Um meine Frage selbst zu beantworten:

ich habe testweise die MMC_MAX_CLUSTERS_IN_ROW in der mmc_config.h auf 
2048 hochgesetzt. Seit 10 Tagen Dauerbetrieb keine Probleme, alles 
bestens.

Nochmal: super Lib! ;-)

von phanaton (Gast)


Lesenswert?

Hi, ich wollte mal einen (höchstwahrscheinlich jedenfalls) Bug melden,
in der Funktion "mmc_wait_ready (void)":
1
static uint8_t mmc_wait_ready (void){
2
3
  TimingDelay = 50;
4
5
  do{
6
    if(   spi_read_byte() == 0xFF ) return TRUE;
7
  }while ( TimingDelay );
8
9
  return FALSE;
10
}

dort würde eine Endloschleife stattfinden wenn die SD/MMC Karte nicht 
antwortet.
Demnach sollte die Korrektur in etwa so außsehen:
1
//...
2
        }while ( TimingDelay-- );
3
//...

von Fabian B. (fabs)


Lesenswert?

Das ist nicht richtig.
TimingDelay wird an anderer Stelle (im Timer Interrupt) dekrementiert.

Gruß
Fabian

von phanaton (Gast)


Lesenswert?

Oh Sorry hab ich wohl einen Fehler gemacht...
Hab nur kurz den Quellcode überflogen und das kam mir komisch vor, aber 
jetzt da ich sehe das TimingDelay ja gar nicht in der Funktion 
initialisiert wird wird mir klar das ich ein wenig weiter in den 
Quellcode hätte schauen müssen...

Gruß
Philipp

von Sven S. (schwerminator)


Lesenswert?

Hi. Die Library läuft bei mir inzwischen recht gut. Wenn ich allerdings 
in der 0.6.4 sowohl MMC_MULTI_BLOCK auf TRUE als auch MMC_OVER_WRITE auf 
FALSE stelle, kommt es zu folgenden Fehlern in file.c:

Error  1  'struct Fat_t' has no member named 'currentSectorNr'
Error  2  'struct Fat_t' has no member named 'startSectors'
Error  3  'struct Fat_t' has no member named 'startSectors'
Error  4  'struct Fat_t' has no member named 'currentSectorNr'
Error  5  'struct Fat_t' has no member named 'startSectors'
Error  6  'struct Fat_t' has no member named 'currentSectorNr'
Error  7  'struct Fat_t' has no member named 'currentSectorNr'

Und Tatsache: Beschriebene Felder befinden sich in anderen Strukturen. 
Ein einfaches Umändern hat bei mir keinen Erfolg gebracht => weitere 
Fehler. Kann es sein, dass da ein paar Dateien/Funktionen aus 
unterschiedlichen Versionen durcheinander geraten sind?

Gruß Sven

von Daniel R. (zerrome)


Lesenswert?

Hallo,

es ist noch schlimmer als nur durcheinander geraten.
Es ist nicht geprüft. Multiblock wird momentan also nicht unterstützt.

Viele Grüße

Daniel

von Thilo M. (Gast)


Lesenswert?

Ich habe momentan auch noch Probleme,

ich schreibe minütlich Datensätze mit je 182 Byte in eine Textdatei.
Nach 4h25min (263 Datensätzen) + 574 Byte Spaltenüberschrift (insgesamt 
49152 Byte, also exakt 48kB) wird die Karte zwar noch angesprochen, aber 
nicht mehr beschrieben.

Bin momentan ratlos, an was das liegen könnte.

von Thilo M. (Gast)


Lesenswert?

Nachtrag:
die verwendete Karte ist eine etwas ältere Kingston 256MB-Karte.
Mit einer MAX 60x 1GB sind die Leuchtzeiten der LED am CS deutlich 
kürzer.
Ich vermute diese alte Kingston-Karte ist zu langsam.

von Michael M. (eos400dman)


Lesenswert?

Hallo,

ich versuche nun auch schon seit ein paar Tagen eine SD Karte (1Gb mit ) 
deiner Lib anzusteuern. Ich komme aber nicht über mmc_init hinaus. Auf 
dem Terminal wird mir nur Boot angezeigt. Hab bereits den 10k Pullup an 
MISO und auch schon alle Verbindungen geprüft. Mein µC ist ein Atmega 
168 und er läuft mit 10Mhz. Zum testen verwende ich deinen Beispielcode.
Ich habe auch schon #define MMC_MAX_SPEED FALSE versucht, aber das hat 
auch nichts gebracht. Was kann ich noch versuchen?

Gruß Michael

von Thilo M. (Gast)


Lesenswert?

Eben nochmal mit neuer Karte getestet, die Datei wird definitiv beim 
Schreiben >48kB zerschossen (nicht mehr lesbar).

Was könnte da schuld sein?

von Michael M. (eos400dman)


Angehängte Dateien:

Lesenswert?

Ich hab jetzt nochmals mit einer anderen Karte getestet. Aber es läuft 
trotzdem nicht. Meine Hardware müsste doch passen, oder?

Gruß Michael

von Michael M. (eos400dman)


Angehängte Dateien:

Lesenswert?

Hallo,

Hab mir die Signale noch mal mit dem Oszi angesehen. MOSI und SCK sehen 
wie auf dem Bild aus. Dort ist die Ansteigs- und Abfallszeit zu langsam 
für die SD Karte, oder nicht? Wenn ja woran kann das liegen?

Gruß Michael

von Fabian B. (fabs)


Lesenswert?

Eine Anstiegszeit von 330ns sollte wohl ausreichen. Das sieht eigentlich 
sogar sehr gut aus.

Gruß
Fabian

von Michael M. (eos400dman)


Lesenswert?

Also wenn 330ns iO sind, dann weiß ich auch nicht mehr an was es noch 
liegen kann. Hast du eine Idee?

Gruß Michael

von Fabian B. (fabs)


Lesenswert?

Hast du die Möglichkeit deine ganze Schaltung auf 3.3V laufen zu lassen? 
Dann könntest du den Spannungsteiler zur Karte weglassen -> eine 
mögliche Fehlerquelle weniger.

Gruß
Fabian

von Kurt B. (kurt)


Lesenswert?

Du hast doch hoffentlich am LT1763 noch einen vernüftigen Kondensator, 
außer dem 10nF Popel?

von Michael M. (eos400dman)


Lesenswert?

Ich hab nur am Eingang des Reglers 470µ und 100n und an der Karte 
nochmals 100n.

von Michael M. (eos400dman)


Lesenswert?

Ich hab nur am Eingang des Reglers 470µ und 100n und an der Karte 
nochmals 100n. Am Ausgang hab ich sonst nichts.

von Kurt B. (kurt)


Lesenswert?

Das Datenblatt will aber mindestens 3,3µF am Ausgang! 1µF direkt an der 
Karte werden auch nicht schaden.

von Fabian B. (fabs)


Lesenswert?

Ja, miss mal mit deinem Skop den Spannungseinbruch beim Einschalten der 
Karte. Manche Karten sind da sehr zickig und geben schon bei 
Schwankungen <200mV auf. Und die Stromaufnahme der Dinger ist nicht 
unerheblich.

Gruß
Fabian

von Michael M. (eos400dman)


Lesenswert?

Danke erst mal für eure Tipps. Ich habe jetzt noch mal 22µF für die 3,3 
V Versorgung eingebaut. Jetzt bricht die Versorgungsspannung nicht mehr 
ein, davor schon. Aber auch das hat nichts geholfen.

Gruß Michael

von holger (Gast)


Lesenswert?

>Aber auch das hat nichts geholfen

Spannungsteiler als Pegelkonverter für SD Karten
sind kompletter Schwachsinn. Das wurde hier schon oft
genug durchgekaut.

von Fabian B. (fabs)


Lesenswert?

Wie gesagt, versuch mal die ganze Schaltung wenn möglich mit 3V3 zu 
versorgen... dann keine Pegelkonverter... sonst such ich dir auch 
nochmal ne Schaltung mit aktivem Konverter (getestet) raus.

Gruß
Fabian

von Michael M. (eos400dman)


Lesenswert?

Die ganze Schaltung mit 3V3 wird nicht gehen. Sonst brauch ich wo anders 
wieder Pegelwandler zum Beispiel zum Display oder zum Funkmodul.

Gruß Michael

von Fabian B. (fabs)


Lesenswert?

Vielleicht kannst du ein Testprogramm ohne die zwei Peripherieteile 
laufen lassen?

Gruß
Fabian

von Michael M. (eos400dman)


Lesenswert?

Ich hab jetzt die Schaltung mal mit 3V3 getestet und die 1k8 
"kurzgeschlossen". Die 3k3 gegen Masse sollten ja nicht Sören oder?
Aber es geht trotzdem nicht.

Gruß Michael

von Fabian B. (fabs)


Lesenswert?

Michael Mayer schrieb:
> Die 3k3 gegen Masse sollten ja nicht Sören oder?

Darauf würde ich mich erstmal nicht verlassen...

Wie debuggst Du denn aktuell? Kannst Du sehen, ob die Karte gar nicht 
antwortet oder bei welchem CMD es zum Problem kommt?

Gruß
Fabian

von Michael M. (eos400dman)


Lesenswert?

Ich debugge nur über UART. Ich schreibe mal den Code um, damit ich sehe 
an welchem CMD er Probleme hat.

Gruß Michael

von Matthias L. (mcl024)


Lesenswert?

Hallo

echt gute lib. Bin relativ schnell damit zurecht gekommen und jetzt 
läuft sie auf dem ATXMEGA128A1. Ich habe allerdings ein Problem.

Wie kann ich eine Datei immer wieder lesen ohne die Datei wieder mit 
ffopen zu initialisieren?

von Michael M. (eos400dman)


Lesenswert?

Also ich hab jetzt noch mal genauer getestet.
Das Programm bleibt bereits bei
1
  if (mmc_send_cmd(CMD0, 0) == 1) {      // Enter Idle state
Hängen danach bekomme ich keine Ausgabe über UART mehr.
Wenn ihr weiter Informationen bracht kann ich die nachliefern.
Ich hoffe jetzt kann mir jemand helfen.

Gruß Michael

von Fabian B. (fabs)


Lesenswert?

Hast du die
 TimingDelay
Geschichte in den Basistimer eingefügt?

Gruß
Fabian

von Michael M. (eos400dman)


Lesenswert?

Ich hab das so eingebaut:
1
ISR (TIMER0_COMPA_vect)
2
{
3
  TimingDelay = (TimingDelay==0) ? 0 : TimingDelay-1;
4
}

Und der Timer wird so gestartet:
1
 static void timer0_init(){
2
3
  TimingDelay = 0;    // initialisierung der zaehl variable  
4
5
  TCCR0A = 1<<WGM01;     // timer0 im ctc mode
6
  TIMSK0 = 1<<OCIE0A;    // compare interrupt an
7
8
  TCNT0 = START_TCNT;    // ab wo hochgezaehlt wird,
9
  OCR0A = TOP_OCR;    // maximum bis wo gezaehlt wird bevor compare match  
10
11
  TCCR0B = PRESCALER;    // wenn prescaler gesetzt wird, lauft timer los
12
  sei();          // interrupts anschalten, wegen compare match
13
}

von Matthias L. (mcl024)


Lesenswert?

Ich habe ein Problem beim Lesen meiner microSD-Karte. Wenn ich mir die 
Daten anzeige die gelesen wurden, entdecke ich immer vier Bytes die 
zusätzlich zu den Daten auf der SD-Karte hinzugefügt wurden und zwar 
immer genau nach 512 Bytes folgen 0xB9 0x33 0xFF 0xFE

Woher kommen die?

von Matthias L. (mcl024)


Lesenswert?

Ah jetzt weiss ich es. Das müsste die CRC sein (0xB9, 0x33) und 0xFE das 
Startbyte für den nächsten Block. 0xFF weiss ich noch nicht.

Gibts es auch ein Kommando wo die CRC nicht mit ausgegeben wird?

von Manuel V. (manuelito)


Lesenswert?

Hallo,

Ich habe mir gerade aus dem Wiki die Datei AVR-mmc-0.6.4.zip 
heruntergeladen und versuche die gerade zu kompilieren, allerdings 
bekomme ich folgende Fehlermeldungen:

Error  1  'TCCR0A' undeclared (first use in this function) 
D:\AVR-Studio\sdtest0\sdtest0\main_simple.c  80  2  sdtest0

Error  2  each undeclared identifier is reported only once for each 
function it appears in  D:\AVR-Studio\sdtest0\sdtest0\main_simple.c  80 
2  sdtest0

Error  3  'TIMSK0' undeclared (first use in this function) 
D:\AVR-Studio\sdtest0\sdtest0\main_simple.c  81  2  sdtest0

Error  4  'OCIE0A' undeclared (first use in this function) 
D:\AVR-Studio\sdtest0\sdtest0\main_simple.c  81  14  sdtest0

Error  5  'OCR0A' undeclared (first use in this function) 
D:\AVR-Studio\sdtest0\sdtest0\main_simple.c  84  2  sdtest0

Error  6  'TCCR0B' undeclared (first use in this function) 
D:\AVR-Studio\sdtest0\sdtest0\main_simple.c  86  2  sdtest0

Ich benutze einen ATmega16.


Und noch eine Frage: Ich habe eine "SD-Platine", bei der folgende 
Pinbelegung gegeben ist:
Dat2 - unrouted
CS   - PIN 3 (über 1,8k/3,3k Spannungsteiler)
DI   - PIN 5 (über 1,8k/3,3k Spannungsteiler)
GND  - GND
VCC  - VCC über LF33CV
CLK  - PIN 7 (über 1,8k/3,3k Spannungsteiler)
GND  - GND
DO   - PIN 6 (mit einer 3,3V Zenerdiode von dieser Leitung zu GND)
DAT1 - unrouted

Kann ich diese Platine überhaupt verwenden? Und wenn ja an welchen Port 
soll ich sie am Besten anschließen?
Und welche Anpassungen muss ich dann in den Dateien vornehmen?

Viele Grüße,
Manuelito

von Michael M. (eos400dman)


Lesenswert?

@ Manuel Vossel.
Die Register haben beim Atmega 16 andere Bezeichnungen. Musst du mal im 
Datenblatt nachschauen.

Kann mir keiner bei meinem Problem helfen?
Das Programm bleibt bereits bei
1
 if (mmc_send_cmd(CMD0, 0) == 1) {      // Enter Idle state
stehen.

Gruß Michael

von Fabian B. (fabs)


Lesenswert?

Dann stimmt etwas mit deinem Programm aber nicht, weil hängen bleiben 
dürfte er da doch gar nicht.
 Ich hatte damals viel an dieser Funktion rumgepätscht (siehe auch meine 
Posts zur Init weiter oben) damit sie mit allen meinen Karten lief, aber 
wenn du den "aktuellen" Patchstand hast gibt es auch hier ein Timeout.

Wenn du Interesse hast kann ich dir meine init nochmal posten zum 
Vergleich.

Gruß
Fabian

von Michael M. (eos400dman)


Lesenswert?

Das wäre sehr nett von dir.

Gruß Michael

von Fabian B. (fabs)


Lesenswert?

Ich poste hier mal nur die Init...vielleicht reichts ja:
1
unsigned char mmc_init (void){
2
3
  unsigned char cmd, ty, ocr[4];
4
  unsigned short n, j;
5
6
  spi_init();
7
  mmc_disable();
8
9
  for (n = 100; n; n--) spi_read_byte();    // 80 dummy clocks
10
11
  ty = 0;
12
  j=100;
13
do {
14
  if (mmc_send_cmd(CMD0, 0) == 1) {      // Enter Idle state 
15
    j=0;
16
    TimingDelay = 100;            // Initialization timeout of 1000 msec
17
18
    if (mmc_send_cmd(CMD8, 0x1AA) == 1) {  // SDv2? 
19
      for (n = 0; n < 4; n++){
20
        ocr[n] = spi_read_byte();    // Get trailing return value of R7 resp 
21
        }
22
      if (ocr[2] == 0x01 && ocr[3] == 0xAA) {            // The card can work at vdd range of 2.7-3.6V 
23
      
24
//        while (TimingDelay && mmc_send_cmd(ACMD41, 1UL << 30));  // Wait for leaving idle state (ACMD41 with HCS bit)
25
        while (TimingDelay) {  // Wait for leaving idle state (ACMD41 with HCS bit)
26
          mmc_send_cmd(CMD55, 0);
27
          if(!mmc_send_cmd(ACMD41, 1UL << 30))
28
            break;
29
        }
30
31
        while(TimingDelay) {
32
        if (mmc_send_cmd(CMD58, 0) == 0x00) {    // Check CCS bit in the OCR 
33
          for (n = 0; n < 4; n++){
34
            ocr[n] = spi_read_byte();
35
            }
36
          ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;  // SDv2 
37
/*
38
            if(ocr[0] & 0x40) {
39
             ty = CT_SD2 | CT_BLOCK;
40
            } else {
41
             ty = CT_SD2;  // SDv2 
42
            }
43
*/
44
          break;
45
        }
46
        }
47
//ty = CT_SD2 | CT_BLOCK;
48
49
50
51
      }
52
    } else {        // SDv1 or MMCv3 
53
      if (mmc_send_cmd(ACMD41, 0) <= 1)   {
54
        ty = CT_SD1; 
55
        cmd = ACMD41;  // SDv1 
56
      } else {
57
        ty = CT_MMC; 
58
        cmd = CMD1;    // MMCv3 
59
      }
60
      while (TimingDelay && mmc_send_cmd(cmd, 0));      // Wait for leaving idle state 
61
    }
62
//      if (!TimingDelay || mmc_send_cmd(CMD16, 512) != 0)    // Set R/W block length to 512 
63
//        ty = 0;
64
    if(ty != (CT_SD2 | CT_BLOCK)) {
65
      while(TimingDelay && (mmc_send_cmd(CMD16, 512) != 0));
66
    }
67
    if(!TimingDelay) ty = 0;
68
  } else { j--; }
69
  }while(j>0);
70
  fat.card_type = ty;
71
  mmc_disable(); 
72
73
  if( fat.card_type == 0 ){
74
    return FALSE;
75
  }
76
  #if (MMC_MAX_SPEED==TRUE)
77
    spi_maxSpeed();
78
  #endif
79
80
  return TRUE;
81
}

ich hatte (siehe auch oben bei meinem Patchvorschlag schon angemerkt, 
dass meiner Meinung nach der ACMD41 falsch definiert ist. Bei mir gings 
jedenfalls top nach Änderung:
1
#define  ACMD41  (41) // (0x80+41)  // SEND_OP_COND (SDC)

Ich konnte jedenfalls am Ende alle vorhandenen Karten initialisieren und 
ansprechen.

Genaueres auch oben unter: 
Beitrag "Re: MMC SD library FAT16 FAT32 read write"

Gruß
Fabian

von Manuel V. (manuelito)


Lesenswert?

Also mein Problem hat sich mittlerweile erledigt, ich hatte irgendwie 
ein Hardwareproblem auf meiner Platine.
Ich habe zwar alles mit dem Multimeter durchgepiepst, aber irgendwas 
schien wohl doch kaputt zu sein - mit einer anderen Platine funktioniert 
es nämlich jetzt :-)

Eine Frage habe ich aber noch: Bei ffread() werden ja immer 512 Byte 
gelesen und der Rest zwischengepuffert.
In meinem speziellen Fall wird es allerdings so sein, dass ich alle 40ms 
eine bestimmte Anzahl Byte benötige (wahrscheinlich 432, steht aber noch 
nicht fest), die sich auch nicht ändern wird. Das ganze ist für eine 
LED-Animation, dort will ich einen digitalen RGB-Strip im 25Hz-Takt mit 
Daten füttern. Wäre es dann sinnvoll, diesen Puffer auf 432 Byte (oder 
wieviele es nachher werden) zu verkleinern? Bzw. falls ich mehr brauche 
auf soviel erhöhen?
Da ich mittlerweile einen ATmega644 habe ist RAM nicht mehr so ein 
großes Problem.

Ich blicke den Quellcode leider nicht ganz, daher kann ich nicht 
wirklich sagen, wie dieser Puffer einen Geschwindigkeitsvorteil bringt - 
daher hier die Frage.

Viele Grüße,
Manuelito

von Thilo M. (Gast)


Lesenswert?

Manuel Vossel schrieb:
> Also mein Problem hat sich mittlerweile erledigt, ich hatte irgendwie
> ein Hardwareproblem auf meiner Platine.

Da kann ich auch nur drauf hinweisen, das Problem hatte ich auch!
Es kommt wirklich auf eine sehr ordentliche Hardware mit sauberer, 
stabiler Versorgung an.
Ich hatte das Erweiterungsboard für AVR-NET-IO von Pollin und kann nur 
sagen: Finger weg, das Ding ist Schrott! Falsche Dimensionierung, 
falsche Bauteilwahl, Layout muss angepasst werden (Kratzen und Drähte 
einflicken), SD-Kartenhalter hakt.

Kurz und Gut, wenn man schon Elkos für digitale Technik verwendet, dann 
bitte low-ESR. Der Müll, der von Pollin geliefert wird (step-up-Regler 
statt linear-Spannungsregler für 3.3V), lässt die Karte immer mal wieder 
abschmieren (hängt sich auf). Nachdem ich ordentliche Bauteile 
draufgebaut hatte, lief alles wunderbar.

von Thilo M. (Gast)


Lesenswert?

Mein Problem besteht leider immer noch:

- minutenweises Schreiben, ca. 200 Byte pro Datensatz
- täglich wird ein neues File angelegt
- MMC_MAX_CLUSTERS_IN_ROW auf 16383

Nach zwei Tagen wird ein neues File angelegt und ein Stück weit 
beschrieben, danach bleibt das Chipselect auf low und die Karte hängt 
sich auf (bleibt in der Schreib- oder Lesefunktion hängen). Das neu 
angelegte File ist dann defekt.

Hat irgend jemand eine Lösung für dieses Problem?
Ich bin da irgendwie ratlos.

von Michael M. (eos400dman)


Lesenswert?

Nach langem Suchen hab ich die SD-Karte endlich zum laufen bekommen.

Jetzt hab ich noch zwei Fragen:
1. Kann ich, und wenn ja wie kann ich den verbleibenden Speicherplatz 
bestimme?
2. Wie gehe ich beim trennen der SD-Karte vom AVR ab besten vor? Ich hab 
einen Taster den ich drücken will bevor ich die Karte abziehe. Aber wie 
beende ich die Kommunikation ordnungsgemäß?

Gruß Michael

von Fabian B. (fabs)


Lesenswert?

Hallo Michael,
 woran lag's denn schlussendlich?

Zu 1) Gute Frage ;-)
Zu 2) ein fflushFileData() und danach ein ffclose() sollten alles nötige 
erledigen.

Gruß
Fabian

von Michael M. (eos400dman)


Lesenswert?

Fabian B. schrieb:
> Hallo Michael,
>  woran lag's denn schlussendlich?

Das weiß ich auch nicht genau. Nachdem ich den Spannungsregler 
ausgetauscht habe ging es. Der hat zwar zuvor auch 3,3 V rausgegeben 
aber vielleicht ist er kurz Eingebrochen ( Auf dem Oszi war aber nichts 
zu sehen).

Gruß Michael

von Peter S (Gast)


Lesenswert?

Hallo,

erst mal Danke für die tolle Vorarbeit hier. Damit habe sogar ich es 
hinbekommen Daten auf SD-Karten zu schreiben.
Doch jetzt bin ich auf ein Problem gestoßen:
Ich bekomme jede 10 Sekunden einen Datenstring den ich auf die Karte 
schreiben möchte (Datei öffnen -> schreiben -> Datei schließen)
Nun habe ich das Problem, dass genau 512 Datensätze geschrieben werden 
und alle weiteren im Nirwana verschwinden.
An der Dateigröße kann es kaum liegen, zu Testzwecken habe ich schon 
viel größere Datenmengen schreiben können. Da habe ich die Datei aber 
nicht ständig auf- und wieder zugemacht. Liegt das evtl. daran?

Ich möchte aber nicht die Datei die ganze Zeit offen lassen, damit die 
Daten nicht verloren gehen, wenn man die Karte aus dem Leser zieht, ohne 
sie vorher sauber zu beenden.

Danke schon mal.

Gruß
Peter

von Peter S (Gast)


Lesenswert?

Dann antworte ich mir mal selber :)

Problem hab ich umgangen, indem ich alle x Durchläufe ein 
fflushfiledata() mache und nur ganz am Ende, wenn ich regulär das 
Programm verlasse. Wenn die Karte nicht ordnungsgemäß entfernt wird, 
gehen nur ein paar Daten verloren und nicht alle.

von Peter S (Gast)


Lesenswert?

Peter S schrieb:
> Programm verlasse.

... ein ffclose() machen.

sorry, vergessen

von Dirk (Gast)


Lesenswert?

Hi zusammen,

so wie ich das sehe, ist es mit den Funktionen nur möglich immer nur 
eine Datei zur Zeit zu öffen. Richtig?

Ich bräuchte eine Lib mit der ich zwei (verschiedene) Dateien zeitgleich 
öffnen kann. Theoretisch würde es reichen das nur eine Datei geschrieben 
und die andere nur gelesen wird.

Wie schwierig / groß wäre die Änderung der Lib?

Danke!

von Fabian B. (fabs)


Lesenswert?

Beschreibe doch mal deinen Anwendungsfall. Meist ist sowas nämlich nur 
auf den ersten Blick nötig...

Gruß
Fabian

von Dirk (Gast)


Lesenswert?

Hi Fabian,

ich habe einen Navtex und DWD (Wetter) Empfänger gebaut, der die 
Textmeldungen auf einer SD Karte speichert (FAT16/32).

Der User kann über ein GLCD die Meldungen auswählen und sich anzeigen 
lassen.
Funktioniert super, da ich bisher nur alle 3 Stunden für ca. 10 Minuten 
Meldungen empfange (Navtex). Die DWD Meldungen hatte ich bisher auch 
stark eingegrenzt. So störte es nicht wenn der User mal für 10 - 20 
Minuten keine Meldungen lesen konnte. (Die Datenübertragung läuft mit 50 
Baud :o)

Jetzt will ich evtl. ständig alle DWD Meldungen aufzeichnen (der Sender 
läuft 24/7) und daher ist fast immer eine Datei geöffnet. Der User hat 
nur noch zwischen den einzelnen Meldungen die Gelegenheit zu lesen. Das 
geht gar nicht :-/

Viele Grüße,
Dirk

von Georg M. (georgmeyer)


Angehängte Dateien:

Lesenswert?

Servus alle miteinander!

Super Paket, gefällt mir super und funktioniert noch viel besser!

Da ich eine energieoptimierte Schaltung entwickle, hatte mich der 
laufende Timer und vor allem der Aufruf der ISR gestört, die permanent 
aufgerufen wurde.

Das habe ich behoben, indem beim setzen der Werte in die Variable 
TimingDelay durch den Aufruf der Funktion TimingDelay_set(uint_8t time) 
erledigt wird.

Die Funktion schaltet anschließend den Timer und dessen Interrupts ein ( 
eine Initialisierung des Timers muss vorher dennoch erfolgen).

Die Variable selber kann weiterhin wie gewohnt verwendet werden.

Die ISR wurde dahingehend verändert, dass sie den Timer und dessen 
Interrupts deaktiviert, sofern die Variable den Wert 0 erreicht hat.

1
ISR (TIMER3_COMPA_vect)
2
{
3
  if (TimingDelay--==0)
4
  {
5
     TCCR3B=0;  // disable timer
6
     TIMSK3 &= ~(1<<OCIE3A); // disable timer interrupts
7
  }
8
}
9
10
11
12
// *****************************************************************************************************************
13
static void timer3_init(){
14
15
  TimingDelay = 0;    // initialisierung der zaehl variable  
16
  cli();
17
  TCCR3A = 1<<WGM01;     // timer0 im ctc mode
18
  TIFR3 &=~(1<<OCF3A);  //clearing interrupt flag
19
  TIMSK3 |= 1<<OCIE3A;    // compare interrupt an
20
21
  TCNT3 = START_TCNT;    // ab wo hochgezaehlt wird,
22
  OCR3A = TOP_OCR;    // maximum bis wo gezaehlt wird bevor compare match  
23
24
  //TCCR3B = PRESCALER;    // wenn prescaler gesetzt wird, lauft timer los
25
  sei();          // interrupts anschalten, wegen compare match
26
}
27
28
static void TimingDelay_set ( uint8_t time)
29
{
30
  TimingDelay=time;
31
  cli();
32
  TIFR3 &=~(1<<OCF3A);  //clearing interrupt flag
33
  TIMSK3 |= (1<<OCIE3A);
34
  TCCR3B = PRESCALER;
35
  sei();
36
}

Die entsprechenden Änderungen in der mmc.c habe ich bereits vorgenommen 
und den Timer und dessen dazugehörigen Parts mit eingebunden...

Da ich den AT90CAN128 verwende, ist der Timer 1 ein 8Bit Timer, weswegen 
ich die entsprechenden Register auf Timer 3 geändert habe.

Die mmc.c befindet sich im Anhang. Es wurde die aktuelle Version 0.6.4 
verwendet.

Viele Grüße und frohes Fest!


Georg

von Fabian B. (fabs)


Lesenswert?

Warum machst du dir so eine Mühe? Wenn du die tieferen Sleep-Modus 
benutzt, werden die Timer eh gestoppt...

Gruß
Fabian

von Georg M. (georgmeyer)


Lesenswert?

Weil die ISR nicht unendlichmal oft aufgerufen werden muss, wenn sie 
nicht gebraucht wird.

MfG

von Fabian B. (fabs)


Lesenswert?

Hast du keinen Basistimer der eh immer läuft? Der kann das ja mit 
machen...

Aber solange die CPU mit Takt X läuft isses für den Stromverbrauch 
zumindest gleich, ob der Timer 1000 oder 1 Mal pro Sekunde aufgerufen 
wird.

Gruß
Fabian

von Torsten (Gast)


Lesenswert?

Hallo!
Ich versuche grad meine SD Karte mit Soft SPI anzusteuern (PORTA), weil 
bei mir schon ein VS1011 am SPI Port hängt und die beiden mögen sich 
anscheinend nicht. Deswegen hab ich mir gedacht, dass ich die SD Karte 
einfach per Soft Spi auf einem anderen Port ansteuere.
Aber es funktioniert gar nicht mit PORTA.
ich hab in der config.h

#define MMC_SOFT_SPI       TRUE

geändert und mmc.h meine Pins

#if defined (_AVR_ATmega644_)
#define SPI_MISO       2
#define SPI_MOSI                4
#define SPI_Clock       3
#define SPI_SS        5
#endif

Programm Compiliert, es läuft nicht.

dann hab ich die SPI Pins vom PortB wieder zusätzlich angelötet.
und nochmal kompiliert und es lief.
Aber der Grund ist: in der mmc.c spi_init() warum es auf PORTB läuft und 
auf PORTA nicht.
diese Zeile SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1);
eigentlich braucht man diese Zeile für Soft SPI nicht. oder?
Weil wenn ich diese Zeile wegkommentiere dann läuft es auch auf PORTB 
nicht mehr.
Hab ich vielleich was übersehen?

von Volker W. (volker_w24)


Lesenswert?

Hallo!
Tolle Lib! - die ich nur zum Lesen von Daten von der SD-Karte verwende. 
Bisher hatte ich Daten immer nur vom Stammverzeichnis der Karte gelesen, 
ging mit der Version 0.6.1 auch bestens. Nun möchte ich aber meine Daten 
von Dateien aus 2 Verzeichnisebenen lesen, und dazu munter zwischen den 
Verzeichnissen hin und her wechseln. Mittels ffcd() war es nicht 
möglich, überhaupt in ein Verzeichnis hinein zu wechseln. Daher habe ich 
die jetzt aktuelle Vers. 0.6.4 heruntergeladen. Hier funktioniert ffcd() 
bestens, nacheinander ffcd(Verzeichnis_Ebene_1) , 
ffcd(Verzeichnis_Ebene_2) wechselt auch in die Verzeichnisse, ich kann 
die dortigen Dateien problemlos lesen.
LEIDER komme ich aber aus dem Verzeichnis nicht zurück, d.h. ffcdLower() 
funktioniert nicht. Muss ich evtl. bei den Verzeichnisnamen und 
Dateinamen irgendwas beachten, damit ich auch mal wieder aus einem 
direktory zurück komme? Habe den gesamten Thread durchgelesen - bin aber 
mit dem Problem scheinbar allein?

Gruß Volker

von Dirk (Gast)


Lesenswert?

Keine Ahnung ob das mit der Lib geht:
cd ..
wars zu DOS Zeiten.

von Buzzwang (Gast)


Lesenswert?

Hallo,

Volkers Nachricht kann ich bestätigen.

cdlower tut nicht richtig.
In meinem Fall bin ich ein Verzeichnis tiefer gegangen.
Das erste cdlower tat garnichts. Nach dem 2. cdlower war ich wieder auf 
dem Root.

Verzeichnis löschen geht auch nicht.

Info:
Zum Test habe ich die FAT-Sourcen in ein PC-Projekt (VC6.0) eingebunden.
Jedoch wird nur Fat.c und File.c verwendet.
Von einer SD-Karte habe Disk-Image gemacht.
Mmc.c greift nun auf das Image zu, statt auf SPI.

von Georg M. (georgmeyer)


Angehängte Dateien:

Lesenswert?

For all my lovely friends

True ist ein boolscher Ausdruck etc und blabla...

  #ifndef TRUE
  # define TRUE (1==1)
  #endif

  #ifndef FALSE
  # define FALSE (0==1)
  #endif


macht weniger Probs im Zusammenhang mit anderen Bibliotheken.

Ferner habe ich die entsprechenden Stellen geändert in den Dateien im 
Anhang (Variablen unt Rückgabewerte direkt durch 1 und 0 ersetzte und 
sonst den Status mit if (status) oder if (!Status) ersetzt).

Jetzt schmiert der Kompiler bei mir bei Verwendung der CAN lib von Atmel 
auch nicht mehr ab :)
(war der Fall, doppelte Definierung und so.... )

Viel Spaß damit!


MfG


Ps.: Weiterhin sind die Änderungen bezüglich des Timers enthalten (siehe 
weiter oben im Thread...)

Edit: Wäre super, wenn 'der Herr der Dateien' das mit in die nächste 
Revision rein packt.

von Georg M. (georgmeyer)


Lesenswert?

für die file.c:
1
void ffwrites( uint8_t *s ){
2
    while (*s){
3
      ffwrite(*s++);
4
    }
5
    fat.bufferDirty = 1;
6
  }
7
8
void ffwrites_P(const char *progmem_s)
9
{
10
    register char c;
11
    while ( (c = pgm_read_byte(progmem_s++)) ) 
12
  {
13
        ffwrite(c);
14
    }
15
  fat.bufferDirty = 1;
16
}
17
#endif

für die file.h
1
  #include "avr/pgmspace.h"
2
3
  extern void    ffwrites_P(const char *progmem_s)  ;

damit kann man strings aus dem Flash auf die SD-Karte schreiben.


Ferner gehören die Strukturdeklarationen
File_t in die file.h
und Fat_t und Chain_t in die fat.h

Sonst kommt es verinzelt zu Problemen mit der Umgebung (AVR STudio 5)(in 
unschönen Fällen kompiliert er dann nicht mehr).

in die mmc.h muss
1
#include "fat.h"
eingefügt werden.

von milan (Gast)


Lesenswert?

Hallo zusammen,
wie kann ich zeilenweisse eine TXT Datei auslesen???
Gruss
Milan

von Georg M. (georgmeyer)


Lesenswert?

1. Datei öffnen
2. Daten lesen.

Ein Zeilenende wird durch 0x0d 0x0a gekennzeichnet.


Wenn du diese beiden Bytes in der Reihenfolge gelesen hast, weisst du, 
dass danach eine neue Zeile beginnt.

Schau dir einfach mal eine text Datei auf dem PC mit einem Hex Editor 
wie 'Hex Editor MX' an.

MfG

von milan (Gast)


Lesenswert?

Hallo,
ja so habe ich es probiert,es kommt nur mühl aus.

        unsigned char test54;
  if( MMC_FILE_OPENED == ffopen(file_name,'r') ){
    seek = file.length;
    do{
      strcpy(test54, ffread());
    }while(--seek);
    ffclose();
  }
hier ausgabe.

Was mache ich falsch??
Gruss
Milan

von Georg M. (georgmeyer)


Lesenswert?

1
unsigned char test54;
2
  if( MMC_FILE_OPENED == ffopen(file_name,'r') ){
3
    seek = file.length;
4
    uint8_t temp=0;
5
    uint8_t last_character;
6
    do{
7
      strcpy(test54, ffread());
8
      if ( test54 == 0x0a && last_character== 0x0d)
9
       {
10
          // Zeilenumbruch
11
       }
12
      else
13
      {
14
        last_character=test54 ;
15
      }
16
17
    }while(temp++<=seek);
18
    ffclose();
19
  }


Du hast die Datei rückwärts, angefangen beim Ende ausgelesen.
Jetzt beginnst du beim Anfang.

Sollte so funktionieren.

Arbeite mit Breakpoints, dann kommst du auch alleine auf die Lösung ;)

von milan (Gast)


Lesenswert?

Hallo zusammen,
ich habe es so jetzt abgeendert:
  unsigned char test54;
  char test56[200];
  if( MMC_FILE_OPENED == ffopen(file_name,'r') ){
    seek = file.length;
    uint8_t temp=0;
    uint8_t last_character;
    do{
      strcpy(test54, ffread());
      if ( test54 == 0x0a && last_character== 0x0d)
       {
         break;
       }
      else
      {
        last_character=test54 ;
  test56[temp] = last_character;

      }

    }while(temp++<=seek);
    ffclose();
  }
  DisplayText(0,10,test56); // heir brauche ich eine Char Array zur 
ausgabe oder einen String;

es kommt nichts raus weil die funktion nie aufhürt du laufen. obwohl 
eine break beim zeilen umbruch ist!

Gruss
Milan

von milan (Gast)


Lesenswert?

Hallo funktioniert immer noch nicht.
kommt nur mühl raus.

Kann mir bitte jemand helfen???

Danke
Gruss
Milan

von milan (Gast)


Lesenswert?

Hallo zusammen,
funktioniert alles bestens!
Den code habe ich verwendet:
1
              
2
char test56[200];
3
  if( MMC_FILE_OPENED == ffopen(file_name,'r') ){
4
    seek = file.length;
5
    uint8_t count=0, count1=0, count2=0;
6
  int c;
7
    uint8_t last_character;
8
   
9
   
10
while(count1<seek) {
11
  count=0;
12
    c=ffread();
13
    while( (c!='\n') )
14
    {
15
      test56[count]=c;
16
      c=ffread();
17
      count++;
18
    count1++;
19
    }
20
    count--;
21
    test56[count]='\0';
22
  DisplayText(0,10*count2,test56);
23
  count2++;
24
}
25
    ffclose();
26
  }

Gruss
Milan

von milan (Gast)


Lesenswert?

Hallo zusammen,
es ist ein neuer Problem aufgetaucht!
1
 if( MMC_FILE_OPENED == ffopen("spot.txt",'r') )
2
  {
3
      
4
      unsigned long int seek =file.length;
5
      
6
      unsigned long int count=0, count2=0;
7
      unsigned long int count1=0;
8
      int zeichen;
9
      char ausgabe[12][50];
10
   
11
      while(seek>=count1) 
12
      {
13
        char test56[260];
14
        count=0;
15
        zeichen=ffread();
16
        while((zeichen!='\n')&&(seek>=count1) )
17
        {
18
            test56[count]=zeichen;
19
            zeichen=ffread();
20
            count++;
21
            count1++;
22
23
            
24
25
            //_delay_ms(50);
26
        }
27
        //count--;
28
        test56[count]='\0';
29
        DisplayText(0,10*count2,test56);
30
        count2++;
31
        
32
        int j;
33
        char d;
34
        int nr2=0,pos2=0;
35
36
        for(j=0;j<strlen(test56)-1;j++) 
37
        {
38
            d=test56[j];
39
            if(d==0) break;
40
    
41
            if(d==',') 
42
            {
43
                // wenn Trennungszeichen
44
                ausgabe[nr2][pos2]=0; // endekennung
45
                nr2++;
46
                pos2=0;
47
                
48
            }
49
            else 
50
            {
51
                // wenn normales zeichen
52
                ausgabe[nr2][pos2]=d; // zeichen speichern
53
                pos2++;
54
            }
55
            
56
        }
57
        
58
      
59
        
60
      }      
61
    ffclose();
62
  }
wenn ich mit der funktion auslese, schreibt mir immer ein paar 
lehrzeichen auf ende. jedes mahl ein paar. obwohl nur lesen ist.

Weiss jemand zufälig warum??
oder was ich da falsch mache??

Danke im Voraus
Milan

von Georg M. (georgmeyer)


Angehängte Dateien:

Lesenswert?

Bugfix von meinem Post vom 20.01.2012 18:01

in der Fat.c war ein Fehler enthalten. Dieser ist nun behoben.


MfG

von Chris (Gast)


Lesenswert?

Hallo und erst mal danke für diese tolle Lib.

Habe so weit alles zum laufen bekommen,
nur bekomme ich beim auslesen der karte nur murx raus.
Eigentlich sollte  -> Inhalt der Testdatei 0123456789 <- ausgelesen 
werden.
Statdessen bekomme ich das hier:
----------------------------------------------------------------
Boot...Ok

Datei wird geoeffnet:

gelesen:





``

ÿ


``
ÿ


`






ÿ


```
``
`




``
---------------------------------------------------------------------
Woran kann das liegen ?

Es wird genau die richtige Anzahl an Chars ausgelesen aber eben falsch 
übermittelt oder so.

Hardware SPI, SANDISK 4GB SDHC, AT90USB1287 @ 8MHz

Liebe Grüße Chris

von Fabian B. (fabs)


Lesenswert?

Meine Glaskugel sagt: deine UART-Baudrate ist falsch.

(Wie gibts du aus? Bist du sicher, dass die Ausgabe ok ist? Mehr Info 
bitte)

Gruß
Fabian

von Chris (Gast)


Lesenswert?

Meine Bautrate scheint OK zu sein, da ich ja folgenden Text angezeigt 
bekomme... nur eben der inhalt der Karte wird falsch gelesen denke ich


Chris schrieb:
> Boot...Ok
>
> Datei wird geoeffnet:
>
> gelesen:
______________________________________________________________________ 
_
Hier mal mein C-Code.
1
#include <stdlib.h>
2
#include <avr/io.h>
3
// In config.h werden alle nötigen Konfigurationen vorgenommen
4
#include <config.h>
5
#include <file.h>
6
#include <fat.h>
7
 
8
// Hardwareabhängig
9
#include <mmc.h>
10
 
11
// Hardwareabhängig, es kann auch eine eigene eingebunden werden !    
12
#include <Rs232.h>
13
 
14
 
15
//**************************************************************************
16
 
17
int main (void)
18
{
19
  DDRB |= (1<<PB5);
20
  PORTB |= (1<<PB4) | (1<<PB5);  
21
22
  rs232_initialisieren(9600);
23
  
24
  while( PINB & (1<<PB4))
25
  {
26
    rs232_text("\nkeine Karte eingesteckt");
27
  }  
28
29
    
30
    rs232_text("\nBoot");
31
 
32
  // Versuch Karte zu Initialisieren, bis es klappt.
33
  // Unbedingt so, weil die Initialiesierung nicht immer
34
  // auf Anhieb klappt.
35
  while (FALSE == mmc_init())
36
  {
37
    nop();
38
  }
39
 
40
  rs232_text("...");
41
 
42
  // Fat initialisieren. Nur wenn das klappt sind weitere
43
  // Aktionen sinnvoll, sonst endet das Programm.
44
  if (!fat_loadFatData())
45
        return -1;
46
 
47
  // Wenn auf dem terminal "Boot... OK" zu lesen ist, ist Init OK.
48
  // Jetzt kann man Schreiben/Anhängen/Lesen.
49
  rs232_text("Ok\n");
50
 
51
52
  
53
54
  // Datei existiert, also lesen.
55
  // Gerade angelegt und beschrieben, oder war schon vorhanden
56
  // und es wurde was angehaengt?
57
  if (MMC_FILE_EXISTS == ffopen("TEST    TXT"))
58
  {
59
60
    rs232_text("\nDatei wird geoeffnet:\n");
61
      // Setzen einer Variable und dann runterzählen geht
62
      // am schnellsten
63
      unsigned long int seek = file.length;
64
 
65
      // Lesen eines chars und Ausgabe des chars.
66
      // Solange bis komplette Datei gelesen wurde.
67
      do {
68
      rs232_text("\n");
69
          rs232_text(ffread());
70
      } while (--seek);
71
 
72
      ffclose();
73
  }
74
75
  else rs232_text("\nDatei konnte nicht gefunden werden");
76
77
78
79
}

von Fabian B. (fabs)


Lesenswert?

Das ist aber nicht der Code zu deiner Ausgabe. Das "gelesen:" wird in 
dem Code ja nirgends geschickt.

Aber kann es sein, dass dein rs232_text() einen Zeiger erwartet, 
ffread() aber einen char zurückgibt? Was ist denn die Deklaration von 
rs232_text()?

Gruß
Fabian

von Chris (Gast)


Lesenswert?

Hallo Fabian...


Fabian B. schrieb:
> Aber kann es sein, dass dein rs232_text() einen Zeiger erwartet,

genau das war auch der Fehler. Hab ich gar nicht dran gedacht.
Jetzt klappt es wunderbar.

Vielen dank für die Hilfe

LG Chris

von Andre I. (scuido)


Lesenswert?

Hey,

ich habe eine Frage. Ich habe das Problem, dass ich geschriebene Strings 
nicht mehr lesen kann.

Das File wird richtig geschrieben und ich kann mit Windows auch drauf 
zurgreifen. Auch werden Strings korrekt angehängt.

Ich bekomme beim Auslesen mit den µC aber immer nur 
0xFA,0x07,0xFA,0x07,...,0xFA,0x07. An der RS232-Kommunikation liegt das 
nicht.

Woran kann das liegen? Ich würde mich freuen, wenn jemand helfen kann :)


// Der Code:
1
int main(void)
2
{  
3
  uint32_t seek;
4
  Initialization();
5
       
6
  //PINA |= (1<<Door_Relay) | (1<<LED1) | (1<<LED2); // Relay einschalten 
7
  
8
  uint8_t file_name [] = "test_file.txt";
9
  uint8_t str [] = "Hallo Datei 2! Andre Iwers ist der Coolste :)";
10
11
  uart1_puts("\nBoot");
12
13
  // sd/mmc config  **************************************************
14
  if( FALSE == mmc_init() )
15
  {
16
    uart1_puts("\nKeine SD gefunden.... Ende....");
17
    return;
18
  } 
19
      
20
  // fat config ******************************************************
21
  if( FALSE == fat_loadFatData() )
22
  {
23
    uart1_puts("\nDateisystem nicht vorhanden.... Ende....");
24
    return;
25
  }
26
27
  // wenn auf dem terminal "Boot...OK" zu lesen ist, war initialisierung erfolgreich!
28
  uart1_puts("...OK\n");
29
30
31
    // if file exists, it will be opened and then append to it.
32
    if( MMC_FILE_OPENED == ffopen(file_name,'r') ){      
33
      ffseek(file.length);
34
         ffwrites(str);        
35
      ffwrite(0x0D);    // new line in file
36
         ffwrite(0x0A);
37
      ffclose();
38
    }        
39
    else if(MMC_FILE_CREATED == ffopen(file_name,'c') ){
40
      ffwrites(str);        
41
      ffwrite(0x0D);    // new line in file
42
         ffwrite(0x0A);
43
      ffclose();
44
    }   
45
46
  // ***************************************************
47
  // read file complete and print via uart!
48
  if( MMC_FILE_OPENED == ffopen(file_name,'r') )
49
  {      
50
    seek = file.length;
51
    do
52
    {
53
      uart1_puts(ffread());            
54
    }while(--seek);
55
    
56
    ffclose();
57
  }
58
  while(1);
59
}


Viele Grüße,
André

von Andre I. (scuido)


Lesenswert?

Habe einen Fehler gefunden...

Hatte versehentlich einen String übertragen und kein Char.
1
  // ***************************************************
2
  // read file complete and print via uart!
3
  if( MMC_FILE_OPENED == ffopen(file_name,'r') )
4
  {      
5
    seek = file.length;
6
    do
7
    {
8
      uart1_putc(ffread());     
9
    }while(--seek);
10
    
11
    ffclose();
12
  }

Jetzt bekomme ich aber immer nur 0x00 als Rückgabewert.

Jemand noch eine Idee?

von Andre I. (scuido)


Lesenswert?

Fehler behoben, scheinbar war das Dateisystem nicht mehr so gesund. Nach 
Formatierung läufts nun wunderbar.

von Milan (Gast)


Lesenswert?

Hallo zusammen,
wie kann man eine zeile in einer TXT datei löschen???

Gruss
Milan

von Christoph Vogel (Gast)


Lesenswert?

@Andre Iwers:

Du hast auch einen 9.3 Dateinamen verwendet, vieleicht zerstört das die 
fat. Laut Doku -http://www.mikrocontroller.net/articles/AVR_FAT32- 
dürfen nur 8.3 Dateinamen verwendet werden.

@Milan:
Deine Frage ist etwas undeutlich. Daten auf der Disk sind physikalisch.
Aber es gibt 2 Möglichkeiten:
1. Die Datei kopieren und dabei die Textzeile überspringen, die alte 
Datei löschen und die neue Datei umbenennen.
2. Wenns nur um's löschen geht kann man die Daten nach der zu löschenden 
Zeile "auf" die zu löschende Zeile "drüberkopieren". -siehe "ffseek"-

sorry, bischen blöd ausgedrückt

Gruß, Christoph

von Andreas H. (andreas_h16)


Lesenswert?

Hallo,

ich hatte Probleme beim Lesen von Dateien deren Name die Form 
<1234567.123> hat, bzw. eine Dateinamenlänge von 10 (ohne den Punkt) bei 
MMC_LFN_SUPPORT = TRUE.

Ich denke der Fehler liegt hier:
1
//***************************************************************************************************************
2
// prueft auf lange dateinamen (lfn), ermittelt anhand des langen dateinamens den kurzen. nur der kurze
3
// enthaelt die noetigen informationen um die datei lesen zu koennen. ist der gesuchte dateiname gefunden
4
// aber im naechsten sektor/cluster ermittelt die funktion selbstaendig diese und holt die informationen !
5
//***************************************************************************************************************
6
static uint8_t fat_loadFileDataFromCluster(uint32_t sec , uint8_t name [])
7
{
8
9
....
10
    // 2.2) ist eintrag ein sfn eintrag?
11
....
12
    // datei gefunden
13
    if( i == 11 && j != 11) // <---- FALSCH
14
    // ersetzen durch
15
    if( i == 11 && j < 13)
16
....
17
}

Könnte das mal jemand verifizieren ?

Danke,
Andreas

von SurtuR (Gast)


Lesenswert?

hi mich würde interessieren wie man auf einfachen weg, unter benutzung 
dieser lib, ab einer bestimmten stelle aus der datei lesen kann. ist 
soetwas möglich? vielleicht habe ichs auch in diesem sehr langen thread 
überlesen.

mfg,
surtur

von Andreas H. (andreas_h16)


Lesenswert?

Mit ffseek vielleicht, wie üblich (o.k. da heißt es fseek) ?

von SurtuR (Gast)


Lesenswert?

wie in etwa würde ein beispielcode aussehen um bis zu einer gewissen 
position durch zu iterieren, und dann ab position n immer x zeichen zu 
lesen. dann wieder ab position x+n+1 und so weiter. :-) oder muss ich 
jedesmal die position merken und dann wieder von vorn bis zur zu 
lesenden position gehen. und von dort aus lesen? wäre nämlich ein 
ziemlicher overhead.

gruß,
surtur

von SurtuR (Gast)


Lesenswert?

wenn ichs mir genau überlege:

natürlich wäre vom dateiende nach vorn lesen auch eine option.
dann bräuchte ich die gelesenen bytes nur umzudrehen.
und nicht erst von vorn bis zu nem index durchzugehen.

sofern soetwas möglich ist.

gruß,
surtur

von Bernd (Gast)


Lesenswert?

Hallo,

gibt es ne Möglichleit, den freien Speicherplatz der SD zu ermitteln?

Gruß

von Sam .. (sam1994)


Lesenswert?

Gibt es trotz "Baustelle" ein Möglichkeit die ffls Funktion zu nutzen? 
Ziel ist es, das Dateien über ein Lcd ausgewählt werden können. Ich habe 
die Funktion bereits so abgewandelt, dass ich nur die Dateinamen 
erhalte. Allerdings sind diese im 8.3 Format und ffopen akzeptiert dies 
anscheinend nicht.

von Fabian B. (fabs)


Lesenswert?

ffopen funktioniert super mit 8.3.

Was genau bekommst du denn als Dateinamen zurück? Hast du mal ein 
Beispiel, auch wie du's dann an ffopen weitergibst?

Gruß
Fabian

von Sam .. (sam1994)


Lesenswert?

In meinem Beispiel "MARI    ESM". Das wird an uart und ffopen 
weitergegeben. Als Fehler erhalte ich MMC_FILE_ERROR, also muss das 
file_flag FALSE sein.

von Sam .. (sam1994)


Lesenswert?

Das Öffnen funktioniert übrigens, wenn ich einen Dateinamen, der alle 8 
Zeichen belegt, übergebe (also wenn keine Leerzeichen im Dateinamen 
sind).

Fabian B. schrieb:
> Hast du mal ein
> Beispiel, auch wie du's dann an ffopen weitergibst?
1
ffopen((uint8_t*)buffer, 'r');

von Sam .. (sam1994)


Lesenswert?

Hat keiner eine Idee?

von Fabian B. (fabs)


Lesenswert?

Kannst du mal das ganze Codesegment posten, bitte? Also von einlesen per 
ffls bis öffnen per ffopen. Inkl. Definition relevanter Variablen.

Gruß
Fabian

von Sam .. (sam1994)


Lesenswert?

1
static void lsRowsOfClust_ex (fptr_t uputs_ptr,uint32_t start_sec){
2
3
  uint16_t row;        // reihen
4
  uint8_t sec;        // sektoren
5
  uint8_t tmp[12];      // tmp string zur umwandlung
6
  uint8_t i;        // um dateinamen zu lesen
7
8
  sec=0;
9
  do{
10
    fat_loadSector( start_sec + sec );  // sektoren des clusters laden
11
    for( row=0; row<512; row+=32 ){    // geht durch reihen des sektors
12
13
      if( (fat.sector[row+11]==0x20||fat.sector[row+11]==0x10) && (fat.sector[row]!=0xE5 && fat.sector[row]!=0x00) ){
14
        
15
        // namen extrahieren und anzeigen
16
        for( i=0 ; i<11 ; i++ ){
17
          tmp[i]=fat.sector[row+i];
18
        }
19
        tmp[i]='\0';
20
        uputs_ptr(tmp);
21
22
        // reihe auf file stuct laden um file.length zu bekommen. koverieren und anzeigen...
23
        /*fat_loadRowOfSector(row);    
24
        uputs_ptr((uint8_t*)" ");
25
        ltostr(file.length,(char*)tmp,12,10);
26
        uputs_ptr(tmp);
27
        uputs_ptr((uint8_t*)"\n");*/
28
      }
29
    }
30
  }while( ++sec < fat.secPerClust );
31
}
32
33
// *******************************************************************************************************************************
34
// zeigt inhalt eines direktory an.
35
// unterscheidung ob man sich im rootDir befindet noetig, weil bei fat16 im root dir eine bestimmt anzahl sektoren durchsucht
36
// werden muessen und bei fat32 ab einem start cluster ! ruft lsRowsOfClust auf um cluster/sektoren anzuzeigen.
37
// *******************************************************************************************************************************
38
void ffls_ex(fptr_t uputs_ptr){
39
40
  uint8_t     sectors;  // variable um durch sektoren zu zaehlen
41
  uint32_t   clusters;  // variable um durch cluster des verzeichnisses zu gehen
42
43
  // bestimmen ab welchem cluster eintraege angezeigt werden sollen, bzw in welchem ordner man sich befindet
44
  clusters = (fat.dir==0) ? fat.rootDir:fat.dir;
45
46
  // root-dir fat16 nach eintrag durchsuchen. es bleiben noch 3 moeglichkeiten: nicht root-dir fat16, nicht root-dir fat32 und root-dir fat32
47
  if(fat.dir==0 && fat.fatType==16){
48
    sectors = 0;
49
    do{
50
      // root-dir eintraege anzeigen
51
      lsRowsOfClust_ex( uputs_ptr, clusters + sectors );
52
      sectors += fat.secPerClust;
53
    }while( sectors < (uint8_t)32 );
54
  }
55
56
  // root-dir fat32 oder nicht root-dir fat32/16, nach eintrag durchsuchen
57
  else {
58
    // durch cluster des verzeichnisses gehen und eintraege anzeigen
59
    while(!((clusters>=0x0ffffff8&&fat.fatType==32)||(clusters>=0xfff8&&fat.fatType==16))){    // prueft ob weitere sektoren zum lesen da sind (fat32||fat16)
60
      lsRowsOfClust_ex( uputs_ptr, fat_clustToSec(clusters) );                  // zeigt reihen des clusters an
61
      clusters = fat_getNextCluster(clusters);                        // liest naechsten cluster des dir-eintrags (unterverzeichniss groeßer 16 einträge)
62
    }
63
  }
64
65
}
66
67
uint8_t current_file;
68
uint8_t selected_file = 0;
69
char buffer[12];
70
71
void getFile(char *ptr)
72
{
73
  if(current_file++ == selected_file)
74
    strcpy(buffer, ptr);
75
}
76
77
int main()
78
{
79
  //Initialisierung SD-Karte / Lcd / Uart
80
  current_file = 0; 
81
  ffls_ex(getFile);
82
  lcd_puts(buffer);
83
  uputs(buffer);
84
  if(MMC_FILE_OPENED != ffopen((uint8_t*)buffer, 'r')) 
85
  {
86
    lcd_puts("\nError opening!");
87
    for(;;);
88
  }
89
}

von Sam .. (sam1994)


Lesenswert?

Die Dateien, die volle 8.3 Zeichen haben, können übrigens nur dank 
dieser vorgeschlagenen Änderung gelesen werden: 
Beitrag "Re: MMC SD library FAT16 FAT32 read write"

Ich vermute, in der fat_loadFileDataFromCluster ist noch ein weiterer 
Fehler drin, der seit Umstellung auf LFN, diese nicht mehr funktionieren 
lässt?

von Stefan Frings (Gast)


Lesenswert?

Hallo Daniel R.

iste die Aussage noch aktuell, dass die Library nich mehrere Dateien 
gleichzeitig öffnen kann?

SDHC Support ist inzwischen drin, habe ich das richt verstanden?

von Stefan Frings (Gast)


Lesenswert?

Hallo Daniel,

es ist mir gelungen, die Library erfolgreich in mein web basiertes I/O 
Modul einzubinden. Ich habe zwar noch keinen Anwendungsfall für den neu 
gewonnenen Speicherplatz, aber das kommt sicher noch.

Ich musste lediglich die SPI Schnittstelle an den ATxmega128D3 anpassen, 
aber das war überhaupt kein Problem. Schwieriger fiel mir die Einbindung 
in uIP (den Webserver), weil der Multi-Threading fähig ist, die avrfat32 
library aber nicht. Aber ich denke, ich habe das nun mit akzeptablen 
Beschränkungen hinbekommen:

- Der Webserver listet nur die ersten 1300 Bytes des 
Inhaltsverzeichnisses auf. Mehr Dateien will ich sowieso nicht ablegen.

- Beim Datei-Download müssen alle anderen konkurrierenden Web-Anfragen 
warten, bis der Download beendet ist oder abgebrochen wurde.

Vielen Dank für die Veröffentlichung der SD/MMC Karten Library. Sie war 
mir eine sehr große Hilfe.

Mein Projekt ist hier: http://stefanfrings.de/avr_io/

von Wolfgang Sch (Gast)


Lesenswert?

Hallo Thilo,

ich habe ein ähnliches Problem, hast Du inzwischen eine Lösung gefunden?

von Wolfgang S. (wolfgangs)


Lesenswert?

Hallo Thilo,
hast Du inzwischen eine Lösung des Problems gefunden? Bir mir tritt der 
gleiche Fehler auf. Nach Reparatur der Datei bleiben exakt 48k 
verfügbar. Setze ich per PC/Editor noch Zeichen an das Ende der Datei - 
abspeichern - schreibt mein Gerät die nächsten Datensätze einwandfrei. 
Wenn nicht, geht die Datei bei weiterem Beschreiben kaputt. 
Offensichtlich passiert das, wenn die Datenbytes genau bis Sektorende 
reichen. Ist es nur 1 Byte mehr, wird ordentlich weiter geschrieben.


Thilo M. schrieb:
> Mein Problem besteht leider immer noch:
>
> - minutenweises Schreiben, ca. 200 Byte pro Datensatz
> - täglich wird ein neues File angelegt
> - MMC_MAX_CLUSTERS_IN_ROW auf 16383
>
> Nach zwei Tagen wird ein neues File angelegt und ein Stück weit
> beschrieben, danach bleibt das Chipselect auf low und die Karte hängt
> sich auf (bleibt in der Schreib- oder Lesefunktion hängen). Das neu
> angelegte File ist dann defekt.
>
> Hat irgend jemand eine Lösung für dieses Problem?
> Ich bin da irgendwie ratlos.

von Thilo M. (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe noch keine Lösung dafür gefunden, aber falls Daniel das mal 
testen will hänge ich eine Datei an, bei der dieser Fehler auftritt.

Zusätzlich die mmc_config.

von Wolfgang S. (wolfgangs)


Lesenswert?

Thilo M. schrieb:
> Ich habe noch keine Lösung dafür gefunden, aber falls Daniel das mal
> testen will hänge ich eine Datei an, bei der dieser Fehler auftritt.
>
> Zusätzlich die mmc_config.

Fehler beim zyklischen Zufügen von Messdaten zu einer bestehenden Datei.

Heute habe ich einen entscheidenden Hinweis gefunden. Offensichtlich hat 
das etwas mit dem Hersteller und dem Kartentyp zu tun. Eines meiner 
Geräte (hatte ich ganz vergessen) läuft seit 35 Tagen mit zyklischem 
Abspeichern 15s/je ca.60 Byte unter Verwendung einer billigen SD-Card. 
Bei teuren ATP-Industrial-Grade - Karten - 512MB steigt die Geschichte 
bei einer Dateigröße von 48 oder 54KB aus - und zwar immer genau bei 
einem Sektorwechsel zwischen zwei Speichervorgängen.
Dabei werden Daten in den schon benutzten Datenbereich an falscher 
Stelle abgelegt. Es entstehen u.a. neue Dateinamen, die einen Teil der 
ASCII-Zeichen aus den abgespeicherten Daten enthalten.
Ich werde mich mal mit den Unterschieden zwischen industriellen und 
nichtindustriellen SD-Karten beschäftigen und melde mich wieder.

von Thilo M. (Gast)


Lesenswert?

Wolfgang Sch. schrieb:
> Offensichtlich hat
> das etwas mit dem Hersteller und dem Kartentyp zu tun.

Das habe ich nun auch festgestellt.
Eine uralte 256MB Kingston Karte zeigt diesen Fehler nicht. Sie schreibt 
(bis jetzt) fehlerfrei, hat aber deutlich längere Zugriffszeiten.

Die Motorola Micro-SD (2GB) mit Adapter brach nach 38kB ab (siehe oben 
verlinktes File).
Das Zerstören des Files kann man vehindern, indem man bei 10 erfolglosen 
Initialisierungs- Lese- oder Schreibversuchen den Versuch abbricht. Dann 
sind wenigstens die Daten bis dahin nicht verloren.

von Wolfgang S. (wolfgangs)


Lesenswert?

Thilo M. schrieb:
> Wolfgang Sch. schrieb:
>> Offensichtlich hat
>> das etwas mit dem Hersteller und dem Kartentyp zu tun.
>
> Das habe ich nun auch festgestellt.

Hallo Thilo,

ich glaube, ich habe das Problem beseitigen können.
Probiere mal am Ende der Funktion "fat_writeSector"
einige Dummy-Bytes von der SPI zu lesen. Ebenso in "fat_loadSector"
so etwa:
#if (MMC_WRITE==TRUE)
    if( fat.bufferDirty == TRUE )
      {
      fat.bufferDirty = FALSE;    // buffer kann nicht dirty sein weil 
wird geschrieben
      mmc_write_sector( file.currentSectorNr,fat.sector );      // 
schreiben von sektor puffer


      Takte();  //einige Bytes dummy-Lesen



      }
#endif


Offensichtlich brauchen manche Karten an der Stelle noch ein paar Takte.
Das ist erst mal ein vorläufiges Ergebnis, ich teste mal über ein paar 
Tage.
Jetzt bin ich bei 200KB geloggte Daten, soweit bin ich bisher noch nie 
gekommen.

von Thilo M. (Gast)


Lesenswert?

Hi Wolfgang,

habe getan, was du geraten hast, drei Byte zusaätzlich gelesen, und 
siehe da: die Motorola-Karte schreibt auch weiter (alte Datei von oben 
im Anhang verwendet)!

Werde die auch mal ein paar Tage laufen lassen.

;-)

von Wolfgang S. (wolfgangs)


Lesenswert?

Hallo Thilo,

seit 2 Tagen laufen bei mir 3 Geräte mit Karten verschiedener Hersteller 
fehlerfrei.
Problem gelöst!

von Wolfgang S. (wolfgangs)


Lesenswert?

Kleine Änderung:
Um ganz korrekt zu sein habe ich das dummy-read jetzt nur noch an einer 
Position in "mmc_write_sector" eingefügt. Funktioniert.
..............
  if ( retrys == 0)return FALSE;    // If not accepted, return with 
error
  mmc_disable();

  spi_read_byte();
  spi_read_byte();
  spi_read_byte();
  spi_read_byte();
  spi_read_byte();
  spi_read_byte();

  return TRUE;
  }
.............
In den FALSE - Fällen werden sowieso jede Menge Bytes gelesen - ohne 
Schreiben.

von Wolfgang S. (wolfgangs)


Lesenswert?

Wolfgang Sch. schrieb:
> Kleine Änderung:
> Um ganz korrekt zu sein habe ich das dummy-read jetzt nur noch an einer
> Position in "mmc_write_sector" eingefügt. Funktioniert.
> ..............

Kommando zurück! Mit dieser Änderung treten dann doch wieder Fehler auf.
Ich bleibe jetzt bei der Version vom 13.05.

von Thilo M. (Gast)


Lesenswert?

Ich habe seit Jahresanfang eine Sandisk 1GB Micro-SD am Laufen, alle 
paar Wochen taucht ein Fehler auf: Schreiben des Files wird abgebrochen, 
ab 00:00 Uhr wird ein neues File angelegt (so gewollt) und bei jedem 
Schreibvorgang wird ein neues File mit demselben Filenamen angelegt.

Habe auch dort die Änderung eingefügt, weil zufällig heute dieser Fehler 
auftrat. Der Logger hat sofort korrekt weitergeschrieben, mal sehen 
wie's weitergeht.

von Thilo M. (Gast)


Lesenswert?

Hi Wolfgang,

mit 6 zusätzlich gelesenen Byte (wie du oben beschrieben hast) war bei 
einer Motorola 128MB Micro-SD nach 6144 Byte Schluss. Funktioniert also 
auch nicht immer.

von Wolfgang S. (wolfgangs)


Lesenswert?

Thilo M. schrieb:
> Hi Wolfgang,
>
> mit 6 zusätzlich gelesenen Byte (wie du oben beschrieben hast) war bei
> einer Motorola 128MB Micro-SD nach 6144 Byte Schluss. Funktioniert also
> auch nicht immer.

Bin auf der Suche nach der Ursache. Auf jeden Fall tritt aber kein 
Dateisalat mehr auf - oder? Wie äußert sich bei Dir das Problem? Ich 
vermute, dass früher geschriebene Sektoren nicht mehr vorhanden sind?

von Thilo M. (Gast)


Lesenswert?

Wolfgang Sch. schrieb:
> Auf jeden Fall tritt aber kein
> Dateisalat mehr auf - oder?

Nein, das hatte ich vorher schon ausgeschlossen, indem ich 10 Versuche 
beim Lesen und Schreiben gemacht habe, bei Fehler bricht er einfach ab.

Ich habe die zusätzlichen Byte (Lesen und Schreiben) wieder entfernt und 
habe die Taktrate (clk) auf 500kHz heruntergestellt. Seit vier Tagen 
schreibt er jetzt auf der "Problemkarte" fehlerfrei (minütlich ein 
Datensatz).

Manche Karten scheinen an gewissen Stellen ein kleines Päuschen zu 
benötigen, ist der Takt zu schnell, reicht die Zeit nicht. Wenn ich Zeit 
habe, suche ich die Stelle(n), brauche den Logger aber gerade an einer 
Solaranlage.

von Andre (Gast)


Lesenswert?

Hallo,

wie provoziert Ihr den Fehler? ich schreibe Teilweise meherere 100 MB 
Files auf die Karte und habe bis jetzt noch keine Fehler gehabt.

Schreibe entweder in einem Stück oder mit mehrmaligem öffnen der Datei.

Viele Grüße.

von Thilo M. (Gast)


Lesenswert?

Hi Andre,

die Fehler tauchen bei mir nach mehreren Tagen bis Wochen auf. 
Provoziert habe ich die nicht. Beim einen Logger schreibt er auch 
mehrere Wochen ohne Fehler (tägliche Textfiles mit ca. 220kB), dann 
taucht ein Fehler auf.

von Dietmar W. (Gast)


Lesenswert?

Es ist ein Fehler in der ffcdLower() Funktion,
fat_loadRowOfSector(1); ist falsch!!

richtig ist:
  fat_loadRowOfSector(0x20);

dann funktioniert auch das cd..

uint8_t ffcdLower(void){

  if( fat.dir == 0 )return FALSE;      // im root dir, man kann nicht 
hoeher !

  fat_loadSector(fat_clustToSec(fat.dir));  // laed 1. sektor des 
aktuellen direktory.
  fat_loadRowOfSector(0x20);          // ".." eintrag (parent dir) ist 0 
wenn parent == root
  fat.dir=file.firstCluster;        // dir setzen

  return TRUE;
}
Gruß Dietmar

von Wolfgang S. (wolfgangs)


Lesenswert?

Thilo M. schrieb:
Hallo Thilo,

Du hast recht, der Fehler tritt bei langsamen Takt nicht mehr auf. Ich 
habe jetzt probeweise mal Abspeichern von je 512 Byte programmiert, 
Abtastzeit 10s.
Nach spätestens 3 Minuten tritt der Fehler auf, wenn Takt > 500KHz.
Ursache ist wohl die interne Speicherplatzverwaltung der SD-Karten, die 
sehr viele Speicherzyklen vertragen --> bis zu 10Mio. Praktisch ist der 
Flash auch nur einige 1000mal beschreibbar, die interne Organisation der 
Karte sorgt aber dafür, dass der Speicher möglichst gleichmäßig 
abgenutzt wird.
Diese Umspeicher-Arbeitsschritte macht die Karte allein, ohne äußeres 
Zutun.
Wenn man nun wüsste, wann das passiert, hätten wir das Problem gelöst.
Bin weiter am Testen...

von Thilo M. (Gast)


Angehängte Dateien:

Lesenswert?

Hm...

der Fehler ist immer noch da, trotz 500kHz Takt.
In angehängter Datei wird einfach nicht weitergeschrieben.

von Wolfgang S. (wolfgangs)


Lesenswert?

Thilo M. schrieb:
> Hm...
>
> der Fehler ist immer noch da, trotz 500kHz Takt.
> In angehängter Datei wird einfach nicht weitergeschrieben.

Hallo Thilo,

mir ist nach längerem Test jetzt absolut klar, worin das Problem 
besteht.
Immer, wenn genau bis zum Ende eines Sektors oder Clusters geschrieben 
wird und die Datei dann geschlossen wird, gehen Daten verloren und/oder 
die FAT wird fehlerhaft.
Das kann man simulieren, indem man nicht seine Orginaldaten schreibt, 
sondern  immer 16 oder 32 oder 64.... Byte. Dann tritt der Fehler exakt 
an der gleichen Stelle auf. Kartenart und Hersteller sind egal. Was 
weiter oben angenommen wurde, basierte auf Zufall.
Ich habe jetzt erst mal um den Fehler herumprogrammiert:

ffwrites(Messwerteintrag);
if((file_.cntOfBytes &1) ==0) ffwrite(0x20);

- soll heißen, dass vor dem Schreiben von 0dh 0ah geprüft wird, ob die 
Dateilänge ungerade oder gerade ist. Im letzteren Fall hänge ich noch 
ein Leerzeichen dran.

Seit einigen Tagen läuft es nun ohne Fehler, egal wie schnell, egal 
welcher Kartentyp.

Die Funktion

void fflushFileData(void)

enthält noch einen Fehler, wahrscheinlich ist es irgendwie an dieser 
Stelle falsch:

// wenn fat.cntOfBytes == 0 ist der sektor gerade vorher schon 
geschrieben worden oder es ist noch nichts hinein geschrieben worden. 
dann wert so setzten, dass die schleife uebersprungen wird

count = (file_.cntOfBytes==0) ? 512:file_.cntOfBytes;

Eine Abhilfe habe ich noch nicht gefunden, dazu muss man sich tiefer 
einarbeiten. Vielleicht kann uns Daniel helfen?

von Thilo M. (Gast)


Lesenswert?

Wolfgang Sch. schrieb:
> count = (file_.cntOfBytes==0) ? 512:file_.cntOfBytes;

Man hätte auch schreiben können:

count = (file_.cntOfBytes==0) ? 512:0;

dürfte aber kein Unterschied bei der Funktion sein.
Welcher Fehler taucht denn da auf?

Ist bei dir der Unterstrich nach file (als file_.) überall dran?
Den gibt's bei mir nicht. Evtl. ist das 'ne andere Version?

Ich werde es auch mal testen, gerade Zählerstände zu vermeiden.

von Daniel R. (zerrome)


Lesenswert?

Hallo zusammen,
hab leider sehr viel um die Ohren momentan.
Lese aber schon noch mit hier.

Muss mal sehen das ich meine Entwicklungsumgebung für den FAT kram 
wieder zusammenbaue. Sollte sich das mit den geraden und speziell mit 
den 2er Potenzen bestätigen gehe ich dem auf den Grund.

Viele Grüße

Daniel

von Wolfgang S. (wolfgangs)


Lesenswert?

Thilo M. schrieb:
> Wolfgang Sch. schrieb:
>> count = (file_.cntOfBytes==0) ? 512:file_.cntOfBytes;
>
> Man hätte auch schreiben können:
>
> count = (file_.cntOfBytes==0) ? 512:0;
>
> dürfte aber kein Unterschied bei der Funktion sein.
> Welcher Fehler taucht denn da auf?
>
> Ist bei dir der Unterstrich nach file (als file_.) überall dran?
> Den gibt's bei mir nicht. Evtl. ist das 'ne andere Version?
>
> Ich werde es auch mal testen, gerade Zählerstände zu vermeiden.

Hallo Thilo,
das mit den ungeraden Sektorenlängen habe ich vereinfachend gemacht, um 
gerade komplett gefüllte Sektoren (512 Byte) zu vermeiden. Alle anderen, 
mit einer geraden Anzahl Bytes gefüllter Sektoren werden auch auf 
"ungerade" gebracht, das wäre aber eigentlich nicht nötig.

file_ - Unterstrich:
Die Software wurde auf einem Luminary - Prozessor (ARM-CORTEX) zum 
Laufen gebracht. Compiler:  Keil µVision4.
Bei der Implementierung gab es ein Problem mit der Bezeichnung "file", 
daher der Unterstrich.

Zum Problem:
Ich vermute, dass das Problem darin besteht, dass
fat.bufferDirty = TRUE;
gesetzt wird, wenn
count < 512  (while - Schleife)
aber nicht, wenn
count == 512
Ich werde mal noch ein wenig probieren.

von Fabian B. (fabs)


Lesenswert?

Hat eigentlich mal jemand Lust mit den neuen Erkenntnissen ein Paket zu 
bauen?

Das letzte Paket zu nehmen und dann alle hier gefundenen Fixes 
einzubauen wäre etwas aufwendig.

Vielleicht wäre einer der "Vielverwender" hier dazu bereit?

Gruß
Fabian

von Thilo M. (Gast)


Lesenswert?

Hi Fabian,

ich denke, wenn der Fehler mit den "eben vollen" Sektoren gefunden ist, 
wäre es an der Zeit, da hast du Recht.

Mittlerweile ist es, bis auf diesen Fehler, ziemlich wasserdicht.

Lassen wir Daniel noch Zeit, er kennt seinen Code am besten und dürfte 
wissen, wo er suchen muss. ;-)

von Fabian B. (fabs)


Lesenswert?

Stimmt.
Bisher habe ich die Lib nur für's lesen genutzt, daher habe ich oben 
nach meinem init-Patch nix mehr geupdated. Gerade auch weil's ja 
scheinbar immer wieder Schreibprobleme gab.
Wenn das jetzt wirklich eine Lösung ist, wäre alles zusammen in einem 
"0.7"-release ne tolle Sache.

Gruß
Fabian

von Wolfgang S. (wolfgangs)


Lesenswert?

Daniel R. schrieb:
> Hallo zusammen,
> hab leider sehr viel um die Ohren momentan.
> Lese aber schon noch mit hier.
>
> Muss mal sehen das ich meine Entwicklungsumgebung für den FAT kram
> wieder zusammenbaue. Sollte sich das mit den geraden und speziell mit
> den 2er Potenzen bestätigen gehe ich dem auf den Grund.
>
> Viele Grüße
>
> Daniel

Hallo Daniel,

bin hocherfreut, dass Du noch mal einen Blick darauf wirfst.
Ich konnte aus Platzgründen nicht 512 Byte auf einmal schreiben, deshalb 
16 oder 32 ... Byte. Kann man auch anders machen, z.B. 2x250 Byte, dann 
12 Byte, ev. auch 1x512 Byte -- habe ich aber nicht probiert.
Fehler auslösen:
Wichtig ist nur, dass der Sektor zum Schluss genau bis Ende gefüllt 
wurde.
Bitte für jeden Schreibvorgang

1. Datei öffnen (bzw. neu anlegen)
2. Bytes schreiben
3. Datei schließen

so kann ich bei meinem Gerät den Fehler auslösen.

Viele Grüße,
Wolfgang

von Thilo M. (Gast)


Angehängte Dateien:

Lesenswert?

Scheinbar liegt das Problem nicht nur an den "eben vollen" Sektoren.
Vor zwei Stunden hat er trotz ugerade gehaltener Filegröße einfach 
wieder aufgehört weiterzuschreiben.

Falls es zur Analyse hilft hänge ich da geloggte File mal dran.

von Thilo M. (Gast)


Lesenswert?

Edit:

nachdem ich versucht habe, ein Byte anzuhängen, hat Windows das File als 
schreibgeschützt erkannt und es ließ sich nicht mehr abspeichern.

Scheinbar liegt das Problem in der FAT, nicht an der Datei an sich. 
Irgendwo macht die Software falsche Einträge, warum auch immer.

Ich hatte auch schon den Fall, das der selbe Dateiname 25x vorkam, sich 
aber nur auf eine Datei bezog.

von Thilo M. (Gast)


Lesenswert?

Edit 2:

Karte ist defekt. Lässt sich weder formatieren, noch beschreiben. 
Windows erkennt den Datenträger als schreibgeschützt, egal wie der 
Schiebeschalter steht.

Wäre natürlich ein dummer Zufall, wenn das Stück ausgerechnet jetzt 
gestorben wäre.

von Wolfgang S. (wolfgangs)


Lesenswert?

Thilo M. schrieb:
> Edit 2:
>
> Karte ist defekt. Lässt sich weder formatieren, noch beschreiben.
> Windows erkennt den Datenträger als schreibgeschützt, egal wie der
> Schiebeschalter steht.
>
> Wäre natürlich ein dummer Zufall, wenn das Stück ausgerechnet jetzt
> gestorben wäre.

Hallo Thilo,
bei mir laufen 2 Datenlogger seit 2 Wochen mit 10s Speicherabstand im 
"ungerade" - Modus fehlerfrei. Jedes Mal werden ca. 60 Byte abgelegt.

Gruß, Wolfgang

von Andre (Gast)


Lesenswert?

Hallo,

wie macht sich das bei Euch bemerkbar. Hängt er sich bei Euch auf? Wenn 
ja, in welcher Funktion genau? Ich habe zurzeit das Problem, dass er 
sich kurz nach Start des Logvorgangs aufhängt.

Gruß
André

von Andre (Gast)


Lesenswert?

EDIT1:

ich habe teilweise das Problem, dass er sich in der void 
fat_getFreeClustersInRow(uint32_t offsetCluster) aufhängt
1
 
2
void fat_getFreeClustersInRow(uint32_t offsetCluster){
3
4
  uint16_t cnt=1;    // variable fuer anzahl der zu suchenden cluster
5
6
7
 /// Genau hier hängt er sich auf
8
  while(fat_getNextCluster(offsetCluster)){ // suche des 1. freien clusters
9
    offsetCluster++;
10
  }
11
12
  chain.startSectors = fat_clustToSec(offsetCluster);  // setzen des startsektors der freien sektoren (umrechnen von cluster zu sektoren)
13
  chain.cntSecs = fat.secPerClust;          // da schonmal mindestens einer gefunden wurde kann hier auch schon cntSecs damit gesetzt werden
14
15
  do{                          // suche der naechsten freien
16
    if(0==fat_getNextCluster(offsetCluster+cnt) )  // zaehlen der zusammenhängenden sektoren
17
      chain.cntSecs += fat.secPerClust;
18
    else{
19
      return;                  // cluster daneben ist nicht frei
20
    }
21
    cnt++;
22
  }while( cnt<MMC_MAX_CLUSTERS_IN_ROW );      // wenn man hier raus rasselt, gibt es mehr freie zusammenhaengende als MAX_CLUSTERS_IN_ROW
23
24
25
}

von Thilo M. (Gast)


Lesenswert?

Wolfgang Sch. schrieb:
> bei mir laufen 2 Datenlogger seit 2 Wochen mit 10s Speicherabstand im
> "ungerade" - Modus fehlerfrei.

Bei mir jetzt auch.
Ich hatte den Takt des SPI versehenlich auf 8MBit gelassen, was für das 
DOGm Display kein Problem ist. Nur die alte SD-Karte konnte das nicht 
und hat sich verabschiedet. Die neue PLATINUM 1GB ist für max. 5MBit 
Schreiben spezifiziert und hat mit gelegentlichen Schreibfehlern 
reagiert (Resekt!).

Nun läuft das Ganze mit 1MBit seit Tagen fehlerfrei.
Ich denke, wenn der "Eben-Voll-Fehler" gefunden ist, dann ist das Ganze 
ziemlich wasserdicht.

von Torsten S. (tse)


Lesenswert?

> Nun läuft das Ganze mit 1MBit seit Tagen fehlerfrei.
> Ich denke, wenn der "Eben-Voll-Fehler" gefunden ist, dann ist das Ganze
> ziemlich wasserdicht.

Gratuliere.

Beitrag "MMC/SD-Karte mit FAT16 an AVR"
läuft bei mir  ~5 Jahren 24/7. Steuert nebenbei ne FB und hat nen 
Webserver. Fehlerfrei.

SCNR

von Thilo M. (Gast)


Lesenswert?

Torsten S. schrieb:
> läuft bei mir  ~5 Jahren 24/7. Steuert nebenbei ne FB und hat nen
> Webserver. Fehlerfrei.

Ja, bei mir läuft der Heizungsregler seit 2008 auch prima (8x PT1000, 
DCF77/RTC, 6 Ausgänge, Dreipunkt-Schrittregler, State-Machine, VBus 
(RESOL) einbindung, DOGm-Display), die SD-Karte kam dazu und dürfte 
jetzt serienreif sein.
Webserver habe ich auch zwei am Laufen, machen keine Probleme mit 
SD-Karte seit 1.1.12.

von A.H. (Gast)


Lesenswert?

Hallo Daniel,

mich würde mal interessieren ob es hier schon irgendwelche Fortschritte 
in Bezug auf den Bug mit der Clusterlänge gibt, ich würde die lib gern 
auf einem atmega128 einsetzen welche Version ist denn da angebracht ? Im 
SVN gibt es die 0.6.1 die hatte ich mir jetzt erstmal runtergeladen und 
damit mal ein paar erste Tests gemacht, das funktionierte soweit. Sollte 
ich besser die 0.6.4 verwenden ? Ich habe mal den Thead quergelesen - so 
ganz schlau werde ich daraus eigentlich nicht welche Version nun noch 
bekannte Bugs enthält.

@Wolfgang Sch.: Was genau hast Du denn geändert ?

von Wolfgang S. (wolfgangs)


Lesenswert?

A.H. schrieb:
> Hallo Daniel,
>
> mich würde mal interessieren ob es hier schon irgendwelche Fortschritte
> in Bezug auf den Bug mit der Clusterlänge gibt, ich würde die lib gern
> auf einem atmega128 einsetzen welche Version ist denn da angebracht ? Im
> SVN gibt es die 0.6.1 die hatte ich mir jetzt erstmal runtergeladen und
> damit mal ein paar erste Tests gemacht, das funktionierte soweit. Sollte
> ich besser die 0.6.4 verwenden ? Ich habe mal den Thead quergelesen - so
> ganz schlau werde ich daraus eigentlich nicht welche Version nun noch
> bekannte Bugs enthält.
>
> @Wolfgang Sch.: Was genau hast Du denn geändert ?

Hallo A.H.

das funktioniert, weil zusätzliche Leerzeichen in der Ausgabedatei nicht 
stören:

ffwrites(Messwerteintrag);  //aus Puffer "Messwerteintrag"
Dateilaenge=file_.cntOfBytes;
if((Dateilaenge &1) ==0) ffwrite(0x20);
ffwrite(0xd);
ffwrite(0xa);

von Edi R. (edi_r)


Lesenswert?

In einem Projekt, bei dem eine SD-Karte als Datenspeicher (FAT16 mit 
SFN) werwendet wird, ist mir unangenehm aufgefallen, dass beim Löschen 
einer Datei immer eine weitere Datei mitgelöscht wird. Mit einem 
Diskeditor habe ich festgestellt, dass zwar der erste Buchstabe beider 
Dateinamen durch 0xE5 ersetzt wird, die zur zusätzlich gelöschen Datei 
gehörenden Cluster werden in der FAT aber nicht als "frei" markiert und 
bleiben belegt.

Auf der Suche nach dem Grund habe ich folgende Codestelle in "file.c" ab 
Zeile 484 entdeckt:
1
  //////// ob ordner oder datei, der sfn und lfn muss geloescht werden!
2
  fat.bufferDirty = TRUE;            // damit beim laden der geaenderte puffer geschrieben wird
3
  do{
4
    fat.sector[row] = 0xE5;
5
    if( row == 0 ){              // eintraege gehen im vorherigen sektor weiter
6
      fat_loadSector(fat.lastSector);    // der davor ist noch bekannt. selbst wenn der aus dem cluster davor stammt.
7
      fat.bufferDirty = TRUE;
8
      row = 512;              // da nochmal row-=32 gemacht wird, kommt man so auf den anfang der letzten zeile
9
    }
10
    row -= 32;
11
  }while(  fat.sector[row+11]==0x0f && (fat.sector[row]&0x40) != 0x40);    // geht durch alle reihen bis neuer eintrag erkannt wird...
12
13
  fat.sector[row] = 0xE5;

Die do..while-Schleife ist doch eigentlich nur für LFN gedacht, oder? 
Wäre es nicht richtiger, die Schleife "andersherum" zu schreiben, also 
so:
1
  //////// ob ordner oder datei, der sfn und lfn muss geloescht werden!
2
  fat.bufferDirty = TRUE;            // damit beim laden der geaenderte puffer geschrieben wird
3
  while(  fat.sector[row+11]==0x0f && (fat.sector[row]&0x40) != 0x40)    // geht durch alle reihen bis neuer eintrag erkannt wird...
4
  {
5
    fat.sector[row] = 0xE5;
6
    if( row == 0 ){              // eintraege gehen im vorherigen sektor weiter
7
      fat_loadSector(fat.lastSector);    // der davor ist noch bekannt. selbst wenn der aus dem cluster davor stammt.
8
      fat.bufferDirty = TRUE;
9
      row = 512;              // da nochmal row-=32 gemacht wird, kommt man so auf den anfang der letzten zeile
10
    }
11
    row -= 32;
12
  }
13
14
  fat.sector[row] = 0xE5;

Dann kommt man überhaupt nicht in die Schleife, falls man keinen LFN 
hat. Ist meine Überlegung richtig?

von A.H. (Gast)


Lesenswert?

@Wolfgang Sch. Danke ich habe das bei mir als bugfix erstmal auch so 
eingebaut.

Mir ist beim testen ein Fehler aufgefallen der in die gleiche Richtung 
zu gehen scheint. Wenn ich am PC eine Datei auf die Speicherkarte 
kopiere z.B. NAME.TXT und der µC soll dann auf die gleiche Speicherkarte 
in die gleiche Datei schreiben gibt es die Daten anschließend zwei mal 
mit identischem Namen und Inhalt aber unterschiedlicher Größe auf der 
Karte.

Wenn ich mit der Datenträgerüberprüfung von XP auf die Karte gehe wird 
putzigerweise kein Fehler gefunden, Windows gibt beim löschen der beiden 
Dateien einen Fehler aus (Datei nicht gefunden) anschließend sind beide 
Dateien weg.

Eine mit Windows auf die Karte kopierte Datei kann ich mir ffrm nicht 
löschen.

Ist das zwischen 0.6.1 und 0.6.4 schon gefixt worden ?

von Andriy (Gast)


Lesenswert?

Hallo alle zusammen.
Ich hab grade die library runtergeladen und an meiner Hard getestet. 
Scheit so weit alles zu funktionieren (riesen dank an Daniel!!!!!) ABER: 
ich hab da noch n Nokia 6100 LCD, dass ueber das selbe SPI geht. Wenn 
man nun zuerst die SD-karte initialisiert usw. und ne Datei liest, bevor 
man etwas mit dem LCD macht, dann klappt's. Wenn man nun nach dem start 
der LCD was macht, dann kommt das Programm einfach nicht weiter. Also 
wie

if( MMC_FILE_OPENED != ffopen("TXT1.TXT",'r') )
  {  mach etwas
  }
  else mach etwas anderes

macht weder etwas noch was anderes. Scheint so, als ob der CS-pin nicht 
richtig tickt....

'Ne Idee was man da macht?

von Edi R. (edi_r)


Lesenswert?

Du hast aber schon zwei CS-Ausgangspins, einen für das LCD und einen 
für die SD-Karte, oder?

von Andriy (Gast)


Lesenswert?

ja sicher doch!
momentan hab ich noch ein Software-SPI hinzugefügt, so dass der LCD da 
drüber läuft. Wenn man solche unabhängige ports benutzt, ist alles OK. 
man kann dateien öffnen, lesen usw. ich hab ne ATMega 64, also viele 
pins, und es wäre nicht weiter kritisch, wenn ich den Software-spi 
lasse, wäre aber trotz dem nicht schlecht rauszufinden, was da los ist.

von Edi R. (edi_r)


Lesenswert?

Kannst Du feststellen, an welcher Stelle er in ffopen() hängen bleibt?

von Milan (Gast)


Lesenswert?

Hallo zusammen,
1
zeile 1
2
zeile 2
3
zeile 3
4
zeile 4
5
zeile 5

das ist eine TXT Datei. Ich will Zeile 3 löschen.

do das es so aussieht:
1
zeile 1
2
zeile 2
3
zeile 4
4
zeile 5

Wie kann ich das machen. Über einen Beispiel würde ich mich freuen.

Danke im Voraus
Milan

von Milan (Gast)


Lesenswert?

im moment benutze ich die funktion.
1
  unsigned long int seek;
2
  unsigned long int countzeichen=0;
3
  unsigned long int countzeilenzeichen=0;
4
  int32_t seekzeile=0;
5
  int zeichen;
6
  char zeile[200];
7
  char strs[200];
8
  bool geloest= false;
9
    if( MMC_FILE_OPENED == ffopen(datei,'r') )
10
    {
11
    seek = file.length;
12
    
13
    
14
    while(seek!=countzeichen)
15
    {
16
      zeichen=ffread();
17
      countzeichen++;
18
      if (zeichen == '\n')
19
      {
20
        seekzeile = file.cntOfBytes;
21
        zeile[countzeilenzeichen]='\0';
22
      
23
        
24
25
        _delay_ms(500);
26
        if (strncmp(zeile,zeilen_bezeichnung,strlen(zeilen_bezeichnung))==0)
27
          {
28
            geloest = true;
29
            
30
            
31
            strcpy(strs, " ");
32
            for (int a=0; a< strlen(zeilen_bezeichnung)-1; a++)
33
            {
34
              strcat(strs, " ");
35
            }
36
                  
37
            file.cntOfBytes= seekzeile-  (strlen(zeilen_bezeichnung)+2);
38
                      
39
            ffwrites(strs);
40
             
41
            ffclose();
42
        
43
            //_delay_ms(20000);
44
            break;
45
          }
46
        countzeilenzeichen=0;
47
        strcpy(zeile, "");
48
      }
49
      else
50
      {
51
        zeile[countzeilenzeichen]=zeichen;
52
      
53
        countzeilenzeichen++;
54
      }
55
    } 
56
  
57
    ffclose();
leider bleiben die daten auf der karte drauf. warum auch immer. In der 
Datei sind die weg, aber ich bekomme fehler wenn ich zeile 2 und 4 
auslese.

Gruss
Milan

von Matze (Gast)


Lesenswert?

Ich tippe mal darauf, wie man es beim PC programmieren auch macht:
Man legt sich eine temporäre datei an. Schreibt da alle Zeilen rein, die 
man behalten will und löscht das die orginal Datei und benennt die 
temporäre Datei um, so dass sie so heißt wie die orginal Datei.

Probier das doch mal.

Grüße

von Milan (Gast)


Lesenswert?

Hallo Matze,
danke für den Tipp, daran habe ich auch gedacht.
Problem ist, dass die Datei bis 50MB oder mehr gross sein kann. Also 1 
zu 1 kopieren geht nicht. Und so viel ich weiss kann ich nur eine Datei 
aufmachen und bearbeiten.

Gruss
Milan

von Matze (Gast)


Lesenswert?

Jo, das stimmt. Du müsstest auslesen, bis dein Speicher voll ist und 
dann dein Speicherinhalt in die temporäre Datei schreiben. Anderes ist 
leider nicht möglich - so weit ich weiß.
Einfach löschen einer Zeile ist aber auch aus Gründen der Datenstruktur 
nicht möglich. Beschäftige dich doch mal damit, wie eine Datei 
eigentlich auf dem Datenträger aussieht. Als Ansatz: leg dir eine Datei 
mit einem kurzen, definierten Inhalt an und öffne die SD- Karte dann mit 
einem HEX- Editor. Suche dann mit dem HEX- Editor nach deiner 
Zeichenfolge als HEX- Werte. Das kannst du auch an deinem PC machen, 
musst nicht extra den µC verwenden.
Wenn du verstanden hast, wie Dateien auf der SD- Karte aussehen, weißt 
du auch, daß ein anderer Weg als mit der temp. Datei echt umständlich zu 
realisieren ist (bis hin zur völligen Unumsetzbarkeit)

von Milan M. (milance)


Lesenswert?

Ist es möglich das ich die zeile ändere:
ALT: zeile 3 --------> NEU: zeile x

damit ich das x ausfiltern kann und nicht anzeigen.

von Matze (Gast)


Lesenswert?

Klar, überschreiben geht. Du musst bloß die Textstelle haben (ffseek ist 
dein Freund)
Aber zu dieser Bibliothek: geplant war das mal als Datenlogger... ;)

Was hast du eigentlich genau vor und wielange brauchst du um 50MB Daten 
zu schreiben?

von Milan M. (milance)


Lesenswert?

Hallo zusammen,
ich habe es geschaft eine zeile zu löschen.
1
file.cntOfBytes= seekzeile-strlen(zeilen_bezeichnung)-2;
2
            for (int a=0; a < strlen(zeilen_bezeichnung)+2; a++)
3
            {
4
              ffwrite(0x0D);
5
            }

und es wird nichts beschädigt.

Gruss
Milan

von Matze (Gast)


Lesenswert?

Fügst du nich nur für jedes Zeichen deiner Zeile einfach ein Return ein 
(0x0D)?

von Milan M. (milance)


Lesenswert?

ja, aber wenn ich die datei aufmache ist die zeile weg.

von A. R. (redegle)


Lesenswert?

Hallo,

wäre sehr nett, wenn mir jemand helfen könnte. Versuche nun seit ein 
paar Wochen schon die Bibliothek zum laufen zu bekommen.

Verwendet einen Atmega644P und dieses Modul von Conrad als Pegelwandler 
http://www.conrad.de/ce/de/product/197220/ um Hardwarefehler zu 
vermeiden.

Für den 10ms Timer (TimingDelay) verwende ich Timer 1.
Dieser zählt bis 16000 bei einem 16MHz Takt und löst somit jede ms ein 
Interrupt aus. Wurde im Interrupt bis 10 gezählt, so werden 10 ms 
abgezogen. Das ganze funktioniert und wurde bereits getestet.
1
volatile uint8_t TimingDelay;  // fuer mmc.c
2
volatile uint8_t Millisekunden_SD = 0;
3
4
ISR(TIMER1_COMPA_vect)//Taktgeber 1ms
5
{
6
  Millisekunden_SD++;
7
  if(Millisekunden_SD==10)
8
  {
9
    TimingDelay = (TimingDelay==0) ? 0 : TimingDelay-1;  
10
    //TimingDelay wird so lange heruntergezählt, bis TimingDelay == 0 ist.
11
    Millisekunden_SD=0;
12
  }
13
}


In mmc_config.h wurden folgende Änderungen vorgenommen:
1
#define MMC_MAX_SPEED     FALSE

In mmc.h wurde folgende Änderung gemacht:
1
#define __AVR_ATmega644__

Verwendet wird das Hardware SPI


In der Hauptdatei wird folgender code ausgeführt:
1
if(TRUE==mmc_init())
2
{
3
  Display_write_OK();
4
}
5
else
6
{
7
  Display_write_Fehler();
8
}
9
  
10
  
11
if(TRUE ==fat_loadFatData())
12
{
13
  Display_write_OK();
14
}
15
else
16
{
17
  Display_write_Fehler();
18
}

Die Initiallisierung funktioniert. Die Funktion fat_loadFatData() 
liefert hingegeben ein FALSE zurück. Konkret liefert die Funktion 
mmc_read_sector() in der Funktion fat_loadFatData() ein FALSE zurück.
1
TimingDelay = 20;
2
do {  // Wait for data packet in timeout of 200ms 
3
  token = spi_read_byte();
4
} while ( (token == 0xFF) && TimingDelay );
5
  
6
if(token != 0xFE){
7
  return FALSE;  // If not valid data token, retutn with error 
8
}
9
//token ist ungleich 0xFE

Jemand eine Idee, woran das liegen könnte?
Die Karte ist FAT32 Formatiert mit einer Blockgröße von 512 Byte. Es 
handelt sich um eine 1 GB PLATINUM SD Karte.

von jens (Gast)


Lesenswert?

Hallo,

ich versuche auch die Sachen zum Laufen zu bekommen.
Ich verwende folgenden Code:

while (mmc_init() !=0)        // rückgabewert 0 dann ist karte 
initialisiert
  {
    LCD_displayStringLn(Line1,20, "Initializing card faild!");
    while(1)
    {
      nop();
    }
  }

  if(0==fat_loadFatData())        // rückgabewert 0 dann sind die fat 
daten bekannt
  {
    LCD_displayStringLn(Line1,20, "Karte ready...");

    // rückgabewert 2 bedeutet, datei ist nicht vorhanden und wurde 
grade angelegt.
    //bereit zum schreiben !
    if(2==ffopen(file_name))
    {
      LCD_displayStringLn(Line2,20, "Datei wurde angelegt!");
      ffwrites((unsigned char*)"Hallo Welt");
      ffclose();
    }

    // hier ist rückgabewerte eigentlich 1, datei ist vorhanden und 
wurde geöffnet.
    //bereit zum lesen !
    else
    {
      unsigned long int seek = 0;
      unsigned int temp = 0;

      LCD_displayStringLn(Line2,20, "Datei bereits vorhanden!");
      seek=file.length;

      ffseek(2);
      temp = ffread();
      LCD_drawUint16(Line7,100,temp);

      LCD_drawUint16(Line8,100,seek);
      ffclose();
    }
  }
Datei anlegen funktioniert suoer. Ich will aus der Datei genau das "a" 
auslesen. Aber ich komme nicht so richtig klar mit dem ffseek(). Wie 
kann ich in der Datei an diese Stelle springen und genau den Buchstaben 
auslesen?

Grüße, Jens

von Milan M. (milance)


Lesenswert?

Hallo zusammen,
ich benute den Code um eine zeile auszulessen:
1
char* lese_zeile(unsigned long int zeilennr)
2
{
3
  unsigned long int seek;
4
  unsigned long int countzeichen=0;
5
  unsigned long int countzeilen=0;
6
  uint16_t countzeilenzeichen=0;
7
  int zeichen;
8
  char zeile[200];
9
    if( MMC_FILE_OPENED == ffopen(datei,'r') )
10
    {
11
    seek = file.length;
12
    countzeilen++;
13
    
14
    while(seek>=countzeichen)
15
    {
16
      zeichen=ffread();
17
      countzeichen++;
18
      if (zeichen == '\n')
19
      {
20
        countzeilen++;
21
      }
22
      while (zeilennr==countzeilen)
23
      { 
24
        zeichen=ffread();
25
        if (zeichen == '\n')
26
        {
27
          zeile[countzeilenzeichen]='\0';
28
          break;
29
        }
30
        zeile[countzeilenzeichen]=zeichen;
31
      
32
        countzeichen++;
33
        countzeilenzeichen++;
34
      }
35
      if(zeilennr==countzeilen)
36
      {
37
        break;
38
      }
39
    } 
40
  
41
    ffclose();
42
    }    
43
    return zeile;
44
}
leider schreibt er mir immer ein paar leer Zeichen am schluss!
Weiss jemand warum???
Bitte um hilfe.
Gruss
Milan

von Milan M. (milance)


Lesenswert?

Hallo zusammen,
ich habe die lösung gefunden.
1
 if( MMC_FILE_OPENED == ffopen(datei,'r') )
2
 {
3
  seek = file.length-1;
4
  file.cntOfBytes=0;

durch das file.cntOfBytes=0 fängt es immer vom 0 an. zu lesen.
Es passiert weil ich funktion in funktion gemacht habe. Und dann fängt 
es da wo es bei der erster funktion aufgehört hat!

Gruss
Milan

von Portierer (Gast)


Lesenswert?

Michael P. schrieb:
> Moin,
>
> die meiste Arbeit haben die Routinen für das Lesen und Schreiben der
> SD-Karte gemacht (wegen neu schreiben und so). Bei den FAT- und
> Dateifunktionen habe ich erstmal nur die Void-Pointer (die ICC430
> Version die ich nutze kann damit nicht um), die ganzen Zählvariablen
> angepasst und natürlich die Funktionsaufrufe der Low-Level-Routinen
> geändert. Eben um zu sehen ob es funktioniert. Und es funtkioniert.
>
> Weitere Anpassungen sind sicherlich noch möglich, mach ich irgendwann
> auch noch.
>
> Michael

Ich hänge gerade auch noch daran, die Lib für MSP430 zu portieren. Magst 
du vlt. schreiben, was genau du jetzt angepasst hast? Bisher habe ich 
sämtliche SPI-Routinen angepasst sowie die zugehörigen Makros wie 
MMC_CS_LOW, MMC_READ etc.

Wo ich Probleme mit dem Compiler bekomme, sind die Arithmetiken auf 
void-Pointer wie bei "void *vsector;". Das kommt zum Glück nur zweimal 
vor. Generell ist das dekr/inkr von void Pointern auch nicht 
standardkonform (weder C, noch C++). Siehe dazu mein Thema hier:

http://www.c-plusplus.de/forum/p2249560#2249560

Frage an Michael P.: Wie hast du das angepasst? Frage allgemein: Sollte 
man das in der Bibliothek nicht generell korrigieren?

Falls es die Hilfsbereitschaft vergrößert:
------------------------------------------
Ich bin bereit, den Quelltext meiner Portierung wenn sie läuft zur 
Verfügung zu stellen. Generell wäre ich dann dafür, dass man z.B. 
sämtliche SPI-Funktionen aus der mmc.h auslagert und eine spi.h o.ä. als 
wirkliche Schnittstelle einführt. Entsprechend der Plattform müssten 
dann nur  Makros in der spi.h angepasst und die Methoden in einer 
spi.c(pp) ausgeprägt werden.

von dummkopp (Gast)


Lesenswert?

hallo,

die lib vom daniel funktioniert sehr gut.
schade das ich wohl zu dumm bin einen string ins unit8_t file_name[]; zu 
bekommen um den Datei Namen in der laufzeit zu generieren.
mit char file_name[10] ginge es, aber die ffopen funktion erwartet ein 
uint8_t. wie macht man das wenn man nicht so en dummkopp is?

1
  uint8_t file_name[10];
2
  char zahl_str [3];
3
4
  // Dateinamen z.B. "Jan12.csv" aus aktuellem Datum zusammensetzen
5
    switch(mon)
6
        {
7
        case  1: file_name[0] = '\0'; file_name[1] = 'J'; file_name[2] = 'a'; file_name[3] = 'n'; break;
8
        case  2: file_name[0] = '\0'; file_name[1] = 'F'; file_name[2] = 'e'; file_name[3] = 'b'; break;
9
        case  3: file_name[0] = '\0'; file_name[1] = 'M'; file_name[2] = 'a'; file_name[3] = 'r'; break;
10
        case  4: file_name[0] = '\0'; file_name[1] = 'A'; file_name[2] = 'p'; file_name[3] = 'r'; break;
11
        case  5: file_name[0] = '\0'; file_name[1] = 'M'; file_name[2] = 'a'; file_name[3] = 'i'; break;
12
        case  6: file_name[0] = '\0'; file_name[1] = 'J'; file_name[2] = 'u'; file_name[3] = 'n'; break;
13
        case  7: file_name[0] = '\0'; file_name[1] = 'J'; file_name[2] = 'u'; file_name[3] = 'l'; break;
14
        case  8: file_name[0] = '\0'; file_name[1] = 'A'; file_name[2] = 'u'; file_name[3] = 'g'; break;
15
        case  9: file_name[0] = '\0'; file_name[1] = 'S'; file_name[2] = 'e'; file_name[3] = 'p'; break;
16
        case 10: file_name[0] = '\0'; file_name[1] = 'O'; file_name[2] = 'k'; file_name[3] = 't'; break;
17
        case 11: file_name[0] = '\0'; file_name[1] = 'N'; file_name[2] = 'o'; file_name[3] = 'v'; break;
18
        case 12: file_name[0] = '\0'; file_name[1] = 'D'; file_name[2] = 'e'; file_name[3] = 'z'; break;
19
          };
20
21
    zahl_str[0] = '\0';
22
    itoa(year % 100, zahl_str, 10);
23
    strcat(file_name, zahl_str); //<--- warning: pointer targets in passing argument 1 of 'strcat' differ in signedness
24
25
    strcat(file_name, ".csv"); // <--- warning: pointer targets in passing argument 1 of 'strcat' differ in signedness

von nichmehrganzsodumm (Gast)


Lesenswert?

ich bin selbst draufgekommen: ich schreib die zeichen einzeln rein.
1
    // Dateinamen aus aktuellem Datum zusammensetzen
2
    switch(mon)
3
        {
4
        case  1: file_name[0] = '\0'; file_name[1] = 'J'; file_name[2] = 'a'; file_name[3] = 'n'; break;
5
        case  2: file_name[0] = '\0'; file_name[1] = 'F'; file_name[2] = 'e'; file_name[3] = 'b'; break;
6
        case  3: file_name[0] = '\0'; file_name[1] = 'M'; file_name[2] = 'a'; file_name[3] = 'r'; break;
7
        case  4: file_name[0] = '\0'; file_name[1] = 'A'; file_name[2] = 'p'; file_name[3] = 'r'; break;
8
        case  5: file_name[0] = '\0'; file_name[1] = 'M'; file_name[2] = 'a'; file_name[3] = 'i'; break;
9
        case  6: file_name[0] = '\0'; file_name[1] = 'J'; file_name[2] = 'u'; file_name[3] = 'n'; break;
10
        case  7: file_name[0] = '\0'; file_name[1] = 'J'; file_name[2] = 'u'; file_name[3] = 'l'; break;
11
        case  8: file_name[0] = '\0'; file_name[1] = 'A'; file_name[2] = 'u'; file_name[3] = 'g'; break;
12
        case  9: file_name[0] = '\0'; file_name[1] = 'S'; file_name[2] = 'e'; file_name[3] = 'p'; break;
13
        case 10: file_name[0] = '\0'; file_name[1] = 'O'; file_name[2] = 'k'; file_name[3] = 't'; break;
14
        case 11: file_name[0] = '\0'; file_name[1] = 'N'; file_name[2] = 'o'; file_name[3] = 'v'; break;
15
        case 12: file_name[0] = '\0'; file_name[1] = 'D'; file_name[2] = 'e'; file_name[3] = 'z'; break;
16
          };
17
18
    zahl_str[0] = '\0';
19
    itoa(year % 100, zahl_str, 10);
20
  file_name[4] = zahl_str[1];
21
  file_name[5] = zahl_str[2];
22
  file_name[6] = 'c';
23
  file_name[7] = 's';
24
  file_name[8] = 'v';

von doofi (Gast)


Lesenswert?

beides war falsch.

jetz geht es aber endlich mit itoa und strcat;

das habe ich geändert:
ffopen((uint8_t*)file_name,'r')
ffwrites((uint8_t*)log_daten)

so setze ich den string file_name zusammen;
1
char file_name[10];
2
char zahl_str [3];
3
4
file_name[0] = '\0';
5
switch(mon)
6
      {
7
        case  1: strcat(file_name, "Jan"); break;
8
  case  2: strcat(file_name, "Feb"); break;
9
  case  3: strcat(file_name, "Mar"); break;
10
  case  4: strcat(file_name, "Apr"); break;
11
  case  5: strcat(file_name, "Mai"); break;
12
  case  6: strcat(file_name, "Jun"); break;
13
  case  7: strcat(file_name, "Jul"); break;
14
  case  8: strcat(file_name, "Aug"); break;
15
  case  9: strcat(file_name, "Sep"); break;
16
  case 10: strcat(file_name, "Okt"); break;
17
  case 11: strcat(file_name, "Nov"); break;
18
  case 12: strcat(file_name, "Dez"); break;
19
      };
20
21
zahl_str[0] = '\0';
22
itoa(year % 100, zahl_str, 10);
23
strcat(file_name, zahl_str);
24
strcat(file_name, ".csv");
25
26
if  ( MMC_FILE_OPENED == ffopen((uint8_t*)file_name,'r') )
27
    { 
28
      ffseek(file.length); // ans Datei Ende springen
29
      sht_write_log();
30
      ffclose();
31
    }
32
if  (MMC_FILE_CREATED == ffopen((uint8_t*)file_name,'c') )
33
    {
34
      sht_write_log(); // SHT Logdaten in neue Datei schreiben
35
      ffclose();
36
    }

nunja, die 2 posts vorher warn echt unnötig, sry -.-

von Mr. Dose (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Leute,

ich möchte gerne diese Bibliothek, welche bisher einen sehr guten 
Eindruck macht, für eine Art Datenlogger benutzen. D.h. es müssen 
lediglich Daten an das Ende einer Datei geschrieben werden können. 
Jedoch habe ich dafür nur einen Atmega16 zur Verfügung und das Hex-File 
ist bei mir jedoch 17,8 KB groß. Es passt als nicht auf den Atmega16. 
Dabei habe ich schon die Compiler-Optimierung auf möglichst geringe 
Speichergröße gestellt und in den Config-Files nur das nötigste an 
Funktionalität aktiviert. Den bisherigen Code zum Testen findet ihr im 
Anhang.

Hat jemand von euch vielleicht noch eine Idee wie sich der Code 
verkleinern lässt, denn eigentlich fehlt ja auch noch der Teil der die 
Daten "erzeugt", welche dann auf der SD-Karte gespeichert werden sollen.
Oder ist es überhaupt möglich diese Bibliothek auf einem Atmega16 zu 
verwenden?

Vielen Dank für eure Hilfe.

von huhu (Gast)


Lesenswert?

hm.. ohne mir deinen Quelltext angeschaut zu haben: warum nimmst du nich 
einen größeren ATmega? Der ATmega32 und 64 sind doch pin-gleich, wenn 
ich mich richtig entsinne...
Dann haste auch auf jeden Fall genug Platz für deine Anwendung.

Grüße,
Matze

von Mr. Dose (Gast)


Lesenswert?

hmmmm, passen die den auch in den Sockel eines Atmega16?

von Fabian B. (fabs)


Lesenswert?

Radio Eriwan: im Prinzip ja.

Der mega32 ist im DIP Gehäuse aber Pin-to-Pin kompatibel.

Gruß
Fabian

von Peter S (Gast)


Lesenswert?

Hi,

ich habe ein sehr seltsames Phänomen mit der lib.
Bei meinem Projekt funktioniert das Schreiben auf die Karte oft so wie 
es soll. Also vom Prinzip her geht es (Das Grundgerüst von dem Projekt 
besteht aus einem Vorgänger Projekt, dass seit einem Jahr nun schon 
einwandfrei funktioniert). Wenn ich aber meinen Code verändere schreibt 
die lib offensichtlich nicht mehr auf die Karte. Es entsteht einfach 
eine leere Datei. Wenn man sich die Karte mit einem Hex Editor anschaut, 
sieht man, dass der letzte geschrieben String sich auf der Karte 
befindet, sonst nichts. Er überschreibt also die Daten auf der Karte 
ständig.
Die lib setzt also nach dem schreiben des Strings aus irgend einem Grund 
die Position innerhalb der Datei wieder auf den Ursprungswert. So werden 
vorhandene Dateien nicht vergrößert und neue sind leer.

Wenn ich dann aber wieder die Änderung im Code beseitige, geht es 
wieder.
Das komische ist aber, dass diese Änderungen nicht mit der lib zu tun 
haben, sprich z.b. wenn ich eine bestimmte if-Abfrage entferne oder 
sowas in der Art. Auf alle Fälle sind die Änderungen eindeutig und haben 
definitif nichts mit der lib zu tun. Ich hatte ja auch schon meine 
memcpy in Verdacht, aber selbst wenn ich die rausnehme geht es nicht 
immer. Also ich gehe davon aus, dass ich nicht ausversehen eine Variable 
der lib mit 0 überschreibe. Aber ich finde nun auch schon seit Tagen 
nicht die Lösung von meinem Problem.

Hatte jemand von Euch so was auch schon mal?
Woran könnte es liegen?

von Peter S. (Gast)


Lesenswert?

Ich weiß nicht, ob mein Fehler wirklich weg ist, aber ich habe auf alle 
Fälle doch noch einen Fehler gefunden: Der Timer war nicht auf 10 ms, 
sondern auf 20 ms eingestellt (die Rache des übernommenen Grundgerüsts, 
das lauft nämlich mit 16, statt jetzt mit 8 Mhz). Auf alle Fälle läuft 
die Software im Moment so wie sie soll.
Kann es wirklich am Timer gelegen haben?

von SurtuR (Gast)


Lesenswert?

Hallo wie kann ich mehrere Dateien auf der SD Karte anlegen und 
beschreiben?
In eine kann ich erfolgreich schreiben, diese wird anschließend 
geschlossen. Auch öffnen, anhängen und schließen lässt sich 
reproduzieren. Sowie ich jedoch in eine zweite Datei anlegen/beschreiben 
möchte, wird diese angelegt, aber nichts wird hineingeschrieben? Was 
kann ich da tun? Sie sind in keinem Fall beide gleichzeitig geöffnet.

Gruß,
Ralf

von Chris (Gast)


Lesenswert?

Hallo Leute,
habe volgenden Code:
1
while(PIND &= (1<<PD7)) // fragt CDI ab, liegt an Masse, wenn eine Karte eingesteckt ist
2
  {
3
    rs232_text("\nkeine Karte eingesteckt");
4
    WDH3224_TEXT(155,5,"SD-Karte ?",2,0);
5
  }
6
7
  WDH3224_TEXT(155,5,"          ",2,0);
8
  rs232_text("\nBoot");
9
  WDH3224_TEXT(180,12,"Boot...",2,0);
10
  
11
  // Versuch Karte zu Initialisieren, bis es klappt.
12
  // Unbedingt so, weil die Initialiesierung nicht immer
13
  // auf Anhieb klappt.
14
  while (FALSE == mmc_init())
15
  {
16
    nop();
17
  }
18
  
19
  rs232_text("...");
20
  
21
  
22
  // Fat initialisieren. Nur wenn das klappt sind weitere
23
  // Aktionen sinnvoll, sonst endet das Programm.
24
  if (!fat_loadFatData())
25
  return -1;
26
  
27
  // Wenn auf dem terminal "Boot... OK" zu lesen ist, ist Init OK.
28
  // Jetzt kann man Schreiben/Anhängen/Lesen.
29
  rs232_text("Ok\n");
30
  WDH3224_TEXT(180,27,"OK",2,0);
31
  
32
33
  
34
35
  // Datei existiert, also lesen.
36
  // Gerade angelegt und beschrieben, oder war schon vorhanden
37
  // und es wurde was angehaengt?
38
  if (MMC_FILE_EXISTS == ffopen("TEST    TXT"))
39
  {
40
    
41
42
    rs232_text("\nDatei wird geoeffnet:\n");
43
    WDH3224_TEXT(150,5,"                  ",1,0);
44
    WDH3224_TEXT(150,5,"Datei wird geöffnet",1,0);
45
    
46
    // Setzen einer Variable und dann runterzählen geht
47
    // am schnellsten
48
    unsigned long int seek = file.length;
49
    char *tmp;
50
    
51
    // Lesen eines chars und Ausgabe des chars.
52
    // Solange bis komplette Datei gelesen wurde.
53
    do 
54
    {
55
      sd_card_string[i] = ffread();
56
      i++;
57
    } 
58
    while (--seek);
59
60
    sd_card_string[i+1] = '\0';
61
    rs232_text(sd_card_string);                  //bis hier waren es  4h 50min Arbeit
62
    rs232_text("\n");
63
64
    
65
    rs232_text("\n\nEOF\n");
66
    ffclose();
67
    
68
    //Nun wird der Komplette String anhand von ; in Einzelne zerlegt
69
    sd_card[0] =  strtok_r(sd_card_string,";",&tmp);      //und hier stecken 5h 50min Arbeit drin
70
    for(i=1;i<=300;i++)
71
    {
72
      sd_card[i] =  strtok_r(NULL,";",&tmp);        //bis hier...also 10h 40min
73
    }                      
74
    
75
76
  }
77
78
  else if(MMC_FILE_NOT_EXISTS == ffopen("TEST    TXT"))
79
  { 
80
    rs232_text("\nDatei konnte nicht gefunden werden");
81
    WDH3224_TEXT(150,1,"Datei konnte nicht gefunden werden",1,0);
82
  }

nun, das ganze hatte ich auf meinem Testboard (AT90USB1287)ausprobiert 
und es lief. Jetzt habe ich es auf das Aktuelle Projekt übertragen 
ATMega1284, das SD-Card Modul ist das gleiche geblieben. Nun lauft das 
programm allerdings nur noch bis zu dem Punkt, wo ich "Boot...OK" lesen 
kann. Danach passiert leider nichts mehr. Das einzige was noch anders 
ist, ist die SD-Card und als ich das mal durchgemessen habe, das CS low 
ist.

LG Chris

von Chris (Gast)


Angehängte Dateien:

Lesenswert?

cs = low ist ja richtig... Denkfehler.
Eine Kommunikation findet scheinbar statt, habe die Signale mal 
nachgemessen, siehe Anhang.

LG Chris

von Chris (Gast)


Lesenswert?

Hallo Leute,

es läuft jetzt fast alles.
Habe jetzt das Problem, das ich die zu lesende datei nicht komplett auf 
ein Array im Controller packen kann, da dazu der Speicher fehlt.
Kann ich irgendwie mit ffseek() an eine Bestimmte Stelle in der Datei 
Springen in abhängigkeit der gefundenen Absätze in der Datei am ende ist 
ja immer ein 0x0D für </r>. Habe daas mit ffseek bisher so verstanden, 
das man die Speicherstelle expliziet vorgeben muss...

Bsp. was ich meine.
Ich will aus Zeile 5 ETWAS LESEN, ALSO MÜSSTE 4X 0X0D ERKANNT WERDEN UND 
AB DER NÄCHSTEN STELLE MÜSSTEN ALLE CHARS GELESEN WERDEN BIS WIEDER 0x0D 
kommt!? Geht das ?

LG Chris

von SurtuR (Gast)


Lesenswert?

hi,

hat keiner ne idee oder antwort für mich auf meine frage weiter oben:
( Beitrag "Re: MMC SD library FAT16 FAT32 read write" ) ?

gruß,
ralf

von Gerhard G. (g_g)


Angehängte Dateien:

Lesenswert?

Hallo,

SurtuR schrieb:
> hat keiner ne idee oder antwort für mich auf meine frage weiter oben:

Ich habe es mit zwei verschiedenen Versionen getestet. Beide 
funktionieren nach dem beigelegten Code einwandfrei. Also- zwei 
geöffnete Dateien einmal beschreiben und beim Zweiten öffnen etwas 
anhängen.

Einmal auf Atxmega Ebene und einmal auf LPCXpresso-LPC1769 Ebene.

Code stammt aus LPC1769 Version. Ist aber kompatible mit dem Original 
(AVR).

Gruß G.G.

von SurtuR (Gast)


Lesenswert?

vielen dank g.g. für die antwort.

hmm vielleicht sollte ich es noch einmal mit der neusten version der lib 
probieren. ich benutzte bisher immer eine version vor der 0.6.4 (ich 
glaub es war die mmc-0.6.zip. vielleicht liegt da der fehler. vielleicht 
liegts auch am gering dimensionierten ram des atmega168. mal schauen.

gruß,
ralf

von SurtuR (Gast)


Lesenswert?

leider hat das ummodeln auf version 0.6.4 nichts gebracht.
ich stehe immer noch vor dem problem, das in die zweite datei nichts 
geschrieben wird nachdem sie angelegt wurde.

// entsprechender Bereich mit version < 0.6.4

// Auszug Begin
                else if (puffer[3]='U')
                {
                    if  ((puffer[4]=='S') && (puffer[5]=='1'))
                    {
                        sram_ledred=puffer[7];
                        sram_ledyello=puffer[9];
                        sram_ledgreen=puffer[11];
                        sram_var1=puffer[13];
                        eeprom_write_byte(&cntlogsd,sram_cntlogsd+1);
                        eeprom_write_byte(&ledred,sram_ledred);
                        eeprom_write_byte(&ledyello,sram_ledyello);
                        eeprom_write_byte(&ledgreen,sram_ledgreen);
                        eeprom_write_byte(&var1,sram_var1);

                        sum=0;
                        for (i=0;i<sizeof(puffer);i++){puffer[i]=0;} 
pufflauf=0;
                        updateleds();
                        uputc(0x06);
                    }
                    else if (puffer[4]=='F')
                    {
                        // wenn ESC U F data  -> speichere data auf 
SD-Karte
                         if(MMC_FILE_EXISTS == ffopen(uptdatei))
            {
              ffseek(file.length);
              uint8_t z;
                            for (z=5;z<13;z++)
                            {
                                ffwrite(puffer[z]);
                            }
              ffclose();
              for (i=0;i<sizeof(puffer);i++){puffer[i]=0;} pufflauf=0;
              sum=0;

            }
                     uputc(0x06);
                    }

                }
// Auszug Ende


// Entsprechender Bereich mit Version 0.6.4

// Auszug Begin

                else if (puffer[3]='U')
                {
                    if  ((puffer[4]=='S') && (puffer[5]=='1'))
                    {
                        sram_ledred=puffer[7];
                        sram_ledyello=puffer[9];
                        sram_ledgreen=puffer[11];
                        sram_var1=puffer[13];
                        eeprom_write_byte(&cntlogsd,sram_cntlogsd+1);
                        eeprom_write_byte(&ledred,sram_ledred);
                        eeprom_write_byte(&ledyello,sram_ledyello);
                        eeprom_write_byte(&ledgreen,sram_ledgreen);
                        eeprom_write_byte(&var1,sram_var1);

                        sum=0;
                        for (i=0;i<sizeof(puffer);i++){puffer[i]=0;} 
pufflauf=0;
                        updateleds();
                        uputc(0x06);
                    }
                    else if (puffer[4]=='F')
                    {
                        // wenn ESC U F data  -> speichere data auf 
SD-Karte
                         if(MMC_FILE_ERROR == ffopen(uptdatei,'r'))
            {
              ffopen(uptdatei,'c');
                            ffclose();
            }

            if(MMC_FILE_OPENED== ffopen(uptdatei,'r'))
            {
                ffseek(file.length);
              uint8_t z;
                            for (z=5;z<13;z++)
                            {
                                ffwrite(puffer[z]);
                            }
              ffclose();
              for (i=0;i<sizeof(puffer);i++){puffer[i]=0;} pufflauf=0;
              sum=0;
            }
                     uputc(0x06);
                    }

                }

// Auszug Ende

von Ralf R. (surtur)


Lesenswert?

Oh ich hätte obigen Code vielleicht doch lieber in einen Dateianhang 
packen sollen.

sorry.

gruß,
Ralf (SurtuR)

von blödkopp (Gast)


Lesenswert?

also irgendwie is da doch noch n bug drin vermute ich.
ich zeichne werte auf, schon ne ganze weile -alle paar minuten. für 
jeden monat wird ne extra datei angelgegt.

sobald die aktuelle zu beschreibende datei aber 76kB gross ist, lässt 
sich die karte nicht mehr beschreiben. sie lässt sich zwar 
initialisieren, aber sobald ein schreibvorgang gestartet wurde, wechselt 
die meldung von "init-ok" auf "init-felher".

es läuft lange gut, aber warum ist nach 76kB schluß?
kann das jemand bestätigen?

am code sollte es nicht liegen, so ein seltsamer fehler...
1
/**************************************************************************************
2
 Funktion zum erzeugen eines DateiNamens für die MMC Karte
3
 Parameter: year  0000 bis 9999
4
            month 00 bis 31
5
 **************************************************************************************/
6
void mmc_file_name(uint16_t year, uint8_t month)
7
  {
8
    char zahl_str[3];
9
10
  file_name[0] = '\0';
11
  zahl_str[0] ='\0';
12
13
    // Dateinamen aus Datum (year, month) zusammensetzen
14
    switch(month)
15
        {
16
        case  1: strcat(file_name, "Jan"); break;
17
        case  2: strcat(file_name, "Feb"); break;
18
        case  3: strcat(file_name, "Mar"); break;
19
        case  4: strcat(file_name, "Apr"); break;
20
        case  5: strcat(file_name, "Mai"); break;
21
        case  6: strcat(file_name, "Jun"); break;
22
        case  7: strcat(file_name, "Jul"); break;
23
        case  8: strcat(file_name, "Aug"); break;
24
        case  9: strcat(file_name, "Sep"); break;
25
      case 10: strcat(file_name, "Okt"); break;
26
        case 11: strcat(file_name, "Nov"); break;
27
        case 12: strcat(file_name, "Dez"); break;
28
          };
29
30
    itoa(year % 100, zahl_str, 10);
31
  strcat(file_name, zahl_str);
32
  strcat(file_name, ".csv");
33
  }
34
35
36
/**************************************************************************************
37
 Funktion die alle 7,5 minuten ausgeführt wird um SHT messdaten zu speichern
38
 **************************************************************************************/
39
void sht_save_log()
40
  {
41
    mmc_file_name(year, mon); // Dateinamen aus aktuellem Datum erzeugen
42
  
43
44
45
  if (MMC_WRITE ==TRUE)    // create and append only if write is TRUE
46
     { // ****************************************************
47
     // if file exists, it will be opened and then append to it.
48
     if  ( MMC_FILE_OPENED == ffopen((uint8_t*)file_name,'r') )
49
         { 
50
         ffseek(file.length); // ans Datei Ende springen
51
         sht_write_log();
52
         ffclose();
53
             }
54
55
     // ***************************************************
56
     // if the file does not exist, it will be created and written to it.
57
     if  (MMC_FILE_CREATED == ffopen((uint8_t*)file_name,'c') )
58
         {
59
           sht_write_log(); // SHT Logdaten in neue Datei schreiben
60
         ffclose();
61
             }
62
     }
63
  }
64
65
/**************************************************************************************
66
 SHT Logdaten auf MMC Karte schreiben
67
68
 Dateiname; z.B: "Jan12.csv"
69
70
 Sht1 01. 20:15:30Uhr 31,13°C 56,08%
71
 Sht2 01. 20:15:30Uhr 30,14°C 55,45%
72
 Sht3 01. 20:15:30Uhr 00,00°C 00,00%
73
 Sht4 01. 20:15:30Uhr 00,00°C 00,00%
74
 **************************************************************************************/
75
void sht_write_log()
76
  {
77
    char zahl_str[4];
78
  uint8_t zahl_speicher; // Wert aus der laufenden Zeit entnehmen damit sich der Rechenwert nicht während der Verarbeitung ändert
79
  char datenreihe[40];
80
81
82
    for (uint8_t i =0; i<4; i++)
83
      {
84
      datenreihe[0] = '\0';
85
          zahl_str[0] = '\0';
86
87
          // Sensor (Sht1 bis Sht4)
88
      strcat(datenreihe, "Sht");
89
      itoa(i+1, zahl_str, 10);
90
      strcat(datenreihe, zahl_str);
91
          strcat(datenreihe, " ");
92
93
      // Tag (01 bis 31)
94
      zahl_speicher = day;
95
      itoa(zahl_speicher, zahl_str, 10);
96
      if  (zahl_speicher <10) {strcat(datenreihe, "0");}
97
          strcat(datenreihe, zahl_str);
98
          strcat(datenreihe, ". ");
99
100
        // Uhrzeit (00:00:00 bis 23:59:59)
101
      zahl_speicher = hh;
102
      itoa(zahl_speicher, zahl_str, 10);
103
      if  (zahl_speicher <10) {strcat(datenreihe, "0");}
104
          strcat(datenreihe, zahl_str);
105
          strcat(datenreihe, ":");
106
      
107
      zahl_speicher = mm;
108
      itoa(zahl_speicher, zahl_str, 10);
109
      if  (zahl_speicher <10) {strcat(datenreihe, "0");}
110
      strcat(datenreihe, zahl_str);
111
          strcat(datenreihe, ":");
112
113
          zahl_speicher = ss;
114
          itoa(zahl_speicher, zahl_str, 10);
115
      if  (zahl_speicher <10) {strcat(datenreihe, "0");}
116
      strcat(datenreihe, zahl_str);
117
      strcat(datenreihe, "Uhr ");
118
      
119
        // Temperaturwert
120
      itoa(sht_temp_mittelwert[i] / 100, zahl_str, 10);
121
        if  (sht_temp_mittelwert[i] / 100 <100) {strcat(datenreihe, "0");}
122
      if  (sht_temp_mittelwert[i] / 100 < 10) {strcat(datenreihe, "0");}
123
          strcat(datenreihe, zahl_str);
124
          strcat(datenreihe, ",");
125
126
      itoa(sht_temp_mittelwert[i] % 100, zahl_str, 10);
127
      if  (sht_temp_mittelwert[i] % 100 < 10) {strcat(datenreihe, "0");}
128
      strcat(datenreihe, zahl_str);
129
           strcat(datenreihe, "°C ");
130
131
      // Luft-Feuchtewert
132
      itoa(sht_feucht_mittelwert[i] / 100, zahl_str, 10);
133
      if  (sht_feucht_mittelwert[i] / 100 <10) {strcat(datenreihe, "0");}
134
      strcat(datenreihe, zahl_str);
135
          strcat(datenreihe, ",");
136
137
          itoa(sht_feucht_mittelwert[i] % 100, zahl_str, 10);
138
      if  (sht_feucht_mittelwert[i] % 100 <10) {strcat(datenreihe, "0");}
139
      strcat(datenreihe, zahl_str);
140
          strcat(datenreihe, "%");
141
142
          // Mittelwerte zurücksetzen
143
      sht_temp_mittelwert[i] =0;
144
      sht_feucht_mittelwert[i] =0;
145
          
146
      // Datenreihe auf SD-Karte schreiben
147
          ffwrites((uint8_t*)datenreihe);
148
149
          // new line in file
150
        ffwrite(0x0D);
151
      ffwrite(0x0A);
152
        };
153
  };

von Thilo M. (Gast)


Lesenswert?

blödkopp schrieb:
> sobald die aktuelle zu beschreibende datei aber 76kB gross ist, lässt
> sich die karte nicht mehr beschreiben.

Was für ein Nickname! :-)

Du hast vermutlich das Problem mit den "eben vollen" Sektoren.
Lies mal die Dateigröße aus und teile sie durch 512. Wenn's ohne 
Nachkommaanteil aufgeht, dann siehe
Beitrag "MMC SD library FAT16 FAT32 read write"
dort wurde gezeigt, wie das Thema umgangen werden kann.

Und achte auf die max. Schreibgeschwindigkeit die deine Karte kann!
Ich bin da auch schon 'reingefallen.

von Thilo M. (Gast)


Lesenswert?

Ups, Link stimmt nicht, hier der richtige:
Beitrag "Re: MMC SD library FAT16 FAT32 read write"

von Chris (Gast)


Lesenswert?

Hallo Leute,
habe gerade das Problem, dass meine Datei nicht mehr gefunden wird.
1
if (MMC_FILE_EXISTS == ffopen("TEST000.TXT"))
2
  {
3
    WDH3224_CLEAR();
4
    WDH3224_TEXT(3,0,"Datei wird geoeffnet",2,0);
5
    
6
    rs232_text("\nDatei wird geoeffnet:\n");
7
8
       
9
    // Phase 1
10
    for( i = 0; i < ZeilenNr - 1; i++ )
11
    {
12
       while( ffread() != '\n' );
13
    }
14
15
    // Phase 2
16
    n = 0;
17
    while( ( get_c = ffread() ) != '\n' )
18
    sd_card_string[n++] = get_c;
19
    sd_card_string[n] = '\0';
20
    
21
    WDH3224_TEXT(20,0,sd_card_string,1,0);
22
    rs232_text(sd_card_string);                
23
    rs232_text("\n");
24
    rs232_text("\nEOF\n");
25
    ffclose();
26
  
27
28
  }
29
30
  else 
31
  { 
32
    rs232_text("\nDatei konnte nicht gefunden werden");
33
    WDH3224_TEXT(150,2," Datei konnte nicht gefunden werden ",1,1);
34
  }

das init der Karte wird mit OK bestätigt und beim öffnen, springt er 
gleich in die ELSE Anweisung. Habe jetzt schon zich mal den Dateinamen 
gewechselt immer auf das Format 8.3 geachtet, die Karte Formatiert und 
acuh mal mehrere Dateien gleichzeitig drauf gepackt zum testen, aber er 
will nie eine  davon öffnen. Hatte das schon jemand? oder kann mir vlt. 
sagen was da falsch laufen könnte?

von blähkopp (Gast)


Lesenswert?

Thilo M. schrieb:
> blödkopp schrieb:
>> sobald die aktuelle zu beschreibende datei aber 76kB gross ist, lässt
>> sich die karte nicht mehr beschreiben.
>
> Du hast vermutlich das Problem mit den "eben vollen" Sektoren.
> Lies mal die Dateigröße aus und teile sie durch 512. Wenn's ohne
> Nachkommaanteil aufgeht, dann siehe
> Beitrag "Re: MMC SD library FAT16 FAT32 read write"
> dort wurde gezeigt, wie das Thema umgangen werden kann.
>
> Und achte auf die max. Schreibgeschwindigkeit die deine Karte kann!
> Ich bin da auch schon 'reingefallen.


also rechne ich
hm, vielen dank für deinen hinweis

von Thilo M. (Gast)


Lesenswert?

Ich meinte, wenn du das Eigenschaften-Fenster der Datei aufmachst, der 
Wert hinter "Größe" (nicht Größe auf Datenträger, die lässt sich immer 
durch 512 teilen).

von Thilo M. (Gast)


Lesenswert?

Thilo M. schrieb:
> der
> Wert hinter "Größe"

Wert in Byte (Win XP), nicht kB hochrechnen.

von Achim (Gast)


Lesenswert?

Hallo,

vielen Dank zunächst mal für diesen tollen Thread.
Ich versuche gerade, die Bibliothek für ein Projekt mit einem ATMEGA128 
zu verwenden. Klappt eigentlich beinahe alles auf Anhieb, ABER....

Beim Erzeugen eines Directories wird dieses auch angelegt, was jedoch 
verdächtig lange dauert. Ca. 1-2 Sekunden @8MHz. Das muss eigentlich in 
einigen ms erledigt sein. Wenn dann in dieses Verzeichnis gewechselt 
werden soll, klappt dies nicht. Das Erzeugen einer neuen Datei findet 
trotzdem im Hauptverzeichnis statt.
Wird die SD-Karte dann unter Windows gelesen, kann nicht in das 
Verzeichnis gewechselt werden, obwohl es angezeigt wird. Es sei 
angeblich nicht verfügbar.
Das Berechnen mit fat_getfree dauert ebenfalls sehr, sehr lang. Da 
kommen schon einige Sekunden zusammen. Der errechnete freie 
Speicherplatz scheint aber zu stimmen.

Ich verwende die die Version 0.6.4, AVR Studio 4.18, WinAVR-20100110.

Getestet habe ich mit einer 32MB, einer 2 GB und einer 16 GB Karte. 
Verhalten ist bei allen identisch. MAX_SPEED wurde auch schon getestet.

Hat jemand noch eine Idee, woran es liegen könnte?

Das Schreiben klappt mit voller Geschwindigkeit ohne jedes Problem. 
Einen Hardwarefehler kann ich eigentlich ausschliessen.



Vielen
Dank

von Lukas (Gast)


Angehängte Dateien:

Lesenswert?

Da ich die Bibliothek fix brauchte und ich keine Lust auf lange 
Diskussionen hier hatte, hab ich die mal debuggt. (allerdings nur für 
sfn und FAT 16) - ich hoffe, dass ich den Rest nicht allzu sehr kaputt 
gemacht habe.

"wichtigste Bugs":
- bei cdLower wurden die zeilen nicht richtig übergeben
- beim Löschen gabs auch ernsthafte Probleme
- bei mkdir muss der Verzeichnisname exakt 11 Zeichen lang sein (auch 
Leerzeichen)

Ich hänge den code mal an, vielleicht interressiert sich jemand dafür
(ich übernehme aber keinen Support und keine Haftung)

von Milan M. (milance)


Lesenswert?

Chris schrieb:
> Hallo Leute,
> habe gerade das Problem, dass meine Datei nicht mehr gefunden wird.
> das init der Karte wird mit OK bestätigt und beim öffnen, springt er
> gleich in die ELSE Anweisung. Habe jetzt schon zich mal den Dateinamen
> gewechselt immer auf das Format 8.3 geachtet, die Karte Formatiert und
> acuh mal mehrere Dateien gleichzeitig drauf gepackt zum testen, aber er
> will nie eine  davon öffnen. Hatte das schon jemand? oder kann mir vlt.
> sagen was da falsch laufen könnte?
Hallo zusammen ich habe das gleiche Problem.
kann jemand bitte helfen. ich komme nicht weiter.
Gruss
Milan

von Milan M. (milance)


Lesenswert?

Hallo zusammen
also es funktioniert wieder. leider nur ohne lange dateiname.

Gruss
Milan

von fauli (Gast)


Lesenswert?

Daniel R. schrieb:
> Hallo zusammen,
> hab leider sehr viel um die Ohren momentan.
> Lese aber schon noch mit hier.
>
> Muss mal sehen das ich meine Entwicklungsumgebung für den FAT kram
> wieder zusammenbaue. Sollte sich das mit den geraden und speziell mit
> den 2er Potenzen bestätigen gehe ich dem auf den Grund.
>
> Viele Grüße
>
> Daniel

hallo,
nach tagen oder wochen geht aufeinmal nix mehr obwohl bis dahin sauber 
messdaten auf MMC gespeichert wurden. das ist echt ärgerlich, hatte ich 
das thema mmc doch schon abgehackt.
hab jetzt mittlerweile mehrere mmc teiber durchprobiert und finde es 
echt schade das gerade dieser anfängerfreundliche leicht zu 
integrierende treiber hier noch bugs drin hat denn der is eigentlich der 
beste.

gruß

von Thilo M. (Gast)


Lesenswert?

fauli schrieb:
> nach tagen oder wochen geht aufeinmal nix mehr obwohl bis dahin sauber
> messdaten auf MMC gespeichert wurden

Hi fauli,
das Problem habe ich auch, nach vielen Monaten einwandfreiem Betrieb 
schreibt der Logger auf einmal nix mehr.

Ich habe den Eindruck, dass es an meinem Kartenadapter liegt 
(Kontaktproblem zur Micro-SD-Karte).
Hatte auch am PC schon Probleme mit den ausgeleierten Adaptern. Evtl. 
hat da jemand Erfahrungen?

von tomZack (Gast)


Lesenswert?

...tuts eigentlich ffrm mittlerweile ?

Habe einige Tests gemacht und es scheint keine Verzeichnisse zu löschen.

ffrm("ABCDE      ");
oder
ffrm("ABCDE");

steigen beide in


file.c
// datei/ordner nicht vorhanden, dann nicht loschen...
  if(FALSE==fat_loadFileDataFromDir(name)){
    return FALSE;
  }


aus.
Das Verzeichnis ist aber vorhanden. Es macht auch keinen Unterschied, ob 
man das Verzeichnis mit dem Controller oder mit Windows anlegt...


GRuß

Tom

von Radek S. (rsikon)


Lesenswert?

Hallo,
Ich benutze bibliotekido Unterstützung MMC / SD:

AVR-mmc-0.6.4.zip
Autor: Daniel R. (zerrome)
Datum: 24.07.2011 08:49

Es funktioniert gut mit MMC, hat SD-Karte nicht unterstützt. Warum?


Radek

von Gregor B. (gregor54321)


Lesenswert?

Gibt es noch ein Repository?
mir ist aufgefallen, dass in mmc.c spi_init() (Version 0.6.4) eine 
direktive fehlt:
1
static void spi_init(void){
2
  MMC_Direction_REG &=~(1<<SPI_MISO);                  // miso auf input
3
  MMC_Write         |= (1<<SPI_MISO);                  // PullUp für Eingang setzen
4
  MMC_Direction_REG |= (1<<SPI_Clock) | (1<<SPI_MOSI) | (1<<SPI_SS);  // clock, mosi + chip select auf output
5
6
// compiler anweisung by gregor: SPE wird sonst immer gesetzt
7
#if (MMC_SOFT_SPI==FALSE)  
8
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1);  // hardware spi: bus clock = idle low, spi clock / 128 , spi master mode
9
#endif
10
  mmc_disable();  // chip select auf high, karte abwaehlen
11
}

von Gregor B. (gregor54321)


Lesenswert?

Wie kann ich bei geöffneter Datei die FAT updaten / zur SD schreiben? Da 
ich noch unkalkulierbare Zustände habe, sind alle gesammelten Daten nach 
einem Reset verloren...

von Edi R. (edi_r)


Lesenswert?

Schade, dass es niemanden mehr gibt, der sich wirklich aktiv um dieses 
brauchbare Projekt kümmert. Daniel R. (zerrome) ist wohl ausgestiegen 
:-(

Aber zur Frage: Du kannst die Änderungen mit fflushFileData() auf die 
SD-Karte schreiben. Damit steigt allerdings die Schreiblast, d. h. es 
gibt mehr Schreibzugriffe.

von Andre (Gast)


Lesenswert?

Guten Abend,

ich habe mal ne Frage. Habt ihr auch hin und wieder das Problem, dass 
die SD sich nicht initialisieren lässt? Ich habe auch das Gefühl, wenn 
ich voher die freien Bytes auslese hängt sie sich noch öfters auf.

Jemand Erfahrung damit, bzw. kann das jemand bestätigen?

Wie schließt ihr die SD an? Irgendwo noch extra Pullups/downs?

Viele Grüße
André

von Edi R. (edi_r)


Lesenswert?

Schade, dass es niemanden mehr gibt, der sich wirklich aktiv um dieses
brauchbare Projekt kümmert. :-(

Ich schaue auch nur sporadisch hier rein, deshalb kommt die Antwort erst 
mit großer Verspätung.

Ich habe Pull-Ups (75 kOhm) an CS (Chip Select) sowie an den unbenutzten 
Datenleitungen DAT1 und DAT2. Beim Initialisieren, also vor dem 
Umschalten auf SPI, müssen diese Leitungen die richtigen Pegel haben. 
Außerdem lege ich über die Versorgungsleitungen einen keramischen 
Stützkondensator mit 100 nF, und zwar möglichst nahe an der SD-Karte.

Bei mir hängt sich die SD-Karte nie auf, aber das Abfragen der freien 
Bytes dauert ziemlich lange. Vielleicht interpretierst Du das nur als 
"Aufhängen". Warte einfach mal länger ab, das kann durchaus Minuten 
dauern.

von Andi M. (rootsquash)


Lesenswert?

Hallo!
Huch, hier ist ja nicht mehr so viel los. Naja, vielleicht hat ja 
trotzdem jemand Lust zu Helfen:

Okay, ich hatte mal wieder ein wenig Zeit an meiner Terrariensteuerung 
weiter zu basteln. Ziel war es den Temperaturverlauf auf einer SD-Karte 
zu speichern.

Grundprinzip des bisherigen Programms:
4 MHz ATMega162, Interrupt über Timer1 jede Millisekunde, die ISR zählt 
dann gegebenenfalls die Uhr weiter und soll sich um die 
Wellenpaketsteuerung der Heizung kümmern.
Die Lichtsteuerung passiert dann im Hauptprogramm. Code-Schnipsel dazu 
finden sich bei Bedarf am Ende des Posts.
Jetzt habe ich aus einem USB-Dongle mit SD-Karten-Leser die Halterung 
ausgelötet und mit einem 74HC4050 an den Hardware-SPI des ATMegas 
gehangen.
Ich habe versucht den Interrupt auf 10 ms zu setzen:
1
        // Configure Timer 1
2
//         TCCR1A = 0x00;
3
        TCCR1B |= (1<<CS10);
4
        OCR1AL = 0x9C40;
5
        TIMSK |= (1<<OCIE1A);   //Allow Compare Interrupt

Als Hauptprogramm habe ich erstmal einfach das Beispielprogramm genommen 
und die UART-Ausgabe durch eine Ausgabe auf das angeschlossene 
LCD-Display ersetzt.
Nach etwas Rumwackeln an der Karte fing er dann auch an auf die Karte zu 
schreiben. Das Ergebnis:
1
ls -l
2
total 0
3
-rw-r--r-- 1 user users 0  1. Jan 1980  TEST.TXT
4
-rw-r--r-- 1 user users 0  1. Jan 1980  TEST.TXT
5
-rw-r--r-- 1 user users 0  1. Jan 1980  TEST.TXT
6
-rw-r--r-- 1 user users 0  1. Jan 1980  TEST.TXT
7
-rw-r--r-- 1 user users 0  1. Jan 1980  TEST.TXT
8
-rw-r--r-- 1 user users 0  1. Jan 1980  TEST.TXT
9
-rw-r--r-- 1 user users 0  1. Jan 1980  TEST.TXT

Die Datei sollte nicht nochmal neu erstellt werden wenn es sie schon 
gibt und eigentlich sollten die Dateien auch einen Inhalt haben. So ganz 
scheint es also noch nicht funktioniert zu haben.
Ausserdem:
Was kann/muss ich tun um dieses Programm auf meinen 1 ms-Timer 
anzupassen?
Wenn es ein Problem mit der Karte gibt bleibt das Programm in 
irgendwelchen Schleifen hängen, was bei der Steuerung der Temperatur 
oder des Lichts störend sein dürfte.
Gibt es dafür bekannte Lösungen die einfach zu implementieren sind und 
zuverlässig funktionieren?
Ich möchte dieses Projekt eigentlich gerne mit einem µC weitermachen, 
auch wenn es  mit einem Raspberry wohl einfacher wäre ;)


Hier die versprochenen Code-Schnipsel (ich hoffe sie sind nicht zu lang 
fürs Forum):
1
  // Configure Timer 1
2
  TCCR1A = 0x00;
3
  TCCR1B |= (1<<CS11) | (1<<WGM12); //Prescaler 8, CTC1 (renamed WGM12) = 1
4
  OCR1A = 500-1; //((4000000/8)/1000) = 500
5
  TIMSK |= (1<<OCIE1A);  //Allow Compare Interrupt
6
7
while(1)
8
  {
9
    wdt_reset();
10
    switch (dcf_status)
11
    {
12
      case 1:  //1: call dcf_sync() to find bit 59/bit 0
13
//und so weiter
14
15
      case 0:  //0: "normal" operation
16
        if(oldsecond!=second)//once per second is enough
17
        {
18
          oldsecond=second;
19
          show_matched_time(1,2);
20
          check_temp();  //check the temperature a few times per minute
21
        }
22
        break;
23
//und so weiter
24
      default: restart_via_watchdog_timeout();
25
    }
26
    sleep_mode();
27
  }
1
ISR(TIMER1_COMPA_vect)
2
{
3
  millisecond++; 
4
  dcf_read_level();
5
  counter_high++;counter_low++;
6
  if((millisecond%200)<dimmer_value*20)
7
  {
8
    OUT_PORT |= (1<<OUT_DIMM);
9
  }
10
  else
11
  {
12
    OUT_PORT &= ~(1<<OUT_DIMM);
13
  }
14
  if(millisecond == 1000)  //RTC +1 second
15
  //{langweilig}
16
}

: Bearbeitet durch User
von Florian (Gast)


Lesenswert?

ffls gibt bei mir nicht alle Dateien im root-Verzeichnis aus...
Weiß jemand woran das liegen kann?

von Wolfgang S. (wolfgangs)


Lesenswert?

Bitte immer daran denken, dass das Problem mit dem "Sektor gerade voll" 
immer noch besteht (siehe viel weiter oben). Also: Immer schön nur eine 
ungerade Datenanzahl auf die Karte schreiben. Dann treten diese 
komischen FAT-Geschichten (Daten weg, plötzlich mehrere Dateien mit 
gleichem Namen usw.) nicht auf.

von Micha (Gast)


Lesenswert?

Bin grade mal durch den Thread "durchgeflogen" - wenn ich das richtig 
verstehe hat der Autor die Weiterentwicklung aufgegeben? Sehr schade 
falls wahr, weil das wirklich ein gutes und nützliches Projekt ist.

Selber experimentier ich grade mit 'ner etwas schrägen Anwendung: 
Dateien auf einem FAT Datenträger, die Container für CP/M Disk-Images 
sind. Wobei ich dann typischerweise Datenblöcke von 512 Byte Größe in 
der Gegend rumschiebe.

Bei der Gelegenheit hab ich (neben allen positiven Aspekten) eine Sache 
an dem Projekt-Code entdeckt der mir nicht optimal erscheint: die 
Funktion ffseek lädt gleich einen 512 Byte Sektor, wenn sie die passende 
absolute Adresse gefunden hat. Fühlt sich aus meiner Sicht irgendwie 
nicht "richtig" an - ffseek sollte diese Adresse nur zurückliefern und 
es dann anderen Funktionen überlassen, ob der Sektor gelesen oder 
geschrieben werden soll.

Just my 2 cents.

Ansonsten: Klasse Projekt!

von Micha (Gast)


Lesenswert?

Hab gestern und heute ein wenig mit der Bibliothek experimentiert, und 
dabei folgenden Fehler gefunden:

In der *main_simple.c* Beispieldatei werden für eine Reihe von 
Systemtakten die Konstanten für den Timer definiert, die Definition für 
20MHz Systemtakt ist fehlerhaft. Dort steht (Version 0.6.4):
1
#if(F_CPU == 20000000)      // error 0.16%
2
  #define TOP_OCR 0x4D
3
  #define START_TCNT 0xB2
4
  #define PRESCALER 0x04
5
#endif

Hier die passenden Werte für diesen Systemtakt:
1
#if(F_CPU == 20000000)      // error 0.16%
2
  #define TOP_OCR 0xC2
3
  #define START_TCNT 0x3D
4
  #define PRESCALER 0x05
5
#endif

von Martin M. (mcmaier)


Lesenswert?

Habe diese Lib auch im Einsatz und bisher mit dem Ungerade-Modus das 
Problem mit den vollen Sektoren umgangen.
Wollte der Sache aber auf den Grund gehen, damit das lästige 
Prüfen-und-Leerzeichen-anhängen entfällt.
Deshalb habe ich die Bibliothek mal genauer untersucht.
Zu Testzwecken habe ich immer 512 Byte auf einmal geschrieben. Wie 
erwartet blieb die Datei jedes Mal bei 32kB "hängen" (Zuordnungseinheit 
32768 Bytes). Beim Schreiben von ungeraden Datenblöcken waren auch 
größere Dateien möglich.

Vor dem Schreiben wird ja immer zuerst ffseek() ausgeführt, um an die 
akutelle Position in der Datei zu gelangen. Dabei bin ich in ffseek() 
auf folgendes gestoßen:
1
// suchen des sektors in dem offset ist
2
  while( offset >= 512 ){
3
    sectors += 1;
4
    offset -= 512;
5
    file.seek += 512;                    
6
    chain.cntSecs -= 1;
7
    
8
    if ( chain.cntSecs == 0 ){
9
      fat_getFatChainClustersInRow(fat_getNextCluster( chain.lastCluster ));
10
      sectors = chain.startSectors;
11
    }
12
  }

Wenn aber der Sektor genau vollgeschrieben ist (Bytes % 512 == 0) und 
keine weiteren Sektoren mehr anstehen, gab das einen Überlauf bei 
chain.cntSecs -= 1;

Habe also folgendes ausprobiert:
1
 while( offset >= 512 ){
2
    sectors += 1;
3
    offset -= 512;
4
    file.seek += 512;   
5
            
6
    if(offset > 0)
7
    {
8
      chain.cntSecs -= 1;
9
    }
10
    
11
    if ( chain.cntSecs == 0 ){
12
      fat_getFatChainClustersInRow(fat_getNextCluster( chain.lastCluster ));
13
      sectors = chain.startSectors;
14
    }
15
  }

Und siehe da, keine Probleme mehr, auch wenn ich immer 512-Byte Blöcke 
geschrieben habe.

Kann das jemand verifizieren?

von Wolfgang S (Gast)


Lesenswert?

Hallo Martin,

ich habe ja vor langer Zeit den Fehler entdeckt, aber nie Zeit gehabt, 
nach der Ursache zu suchen. Mit der Beseitigung dieses Fehlers dürfte 
das Projekt perfekt sein. Einige Geräte laufen bei mir seit Jahren im 
ungerade-Modus fehlerfrei (LUMINARY-CPU's). Ich teste morgen und teile 
das Ergebnis mit.

Danke für Deine Bemühungen!

von Martin M. (mcmaier)


Lesenswert?

Hallo Wolfgang,

leider scheint das auch noch nicht ganz des Rätsels Lösung zu sein.
Habe zwei Datenlogger mit der Modifikation laufen.
Einer läuft tadellos, beim anderen habe ich Sprünge in der Aufzeichnung, 
wenn ein Sektor vollgeschrieben wurde. Da sind dann plötzlich ein paar 
Zeilen vertauscht...
Die Sprünge laufen nach diesem Prinzip (Jede Zeile steht für einen 
Eintrag)
111111
22 555555
666666
777777
        22222
333333
444444

Muss auch mit dem ffseek() zusammenhängen, womit er mit dem Schreiben 
wieder einsteigt...

Hast du schon was herausgefunden?

von Wolfgang S (Gast)


Lesenswert?

Hallo Martin,

tatsächlich ist da immer noch der Wurm drin. Ab 15.Mai habe ich etwas 
mehr Zeit, da werde ich das Problem lösen. Das Hauptproblem ist, dass 
man die komplette Funktionsweise der Software erst mal verstehen muss. 
Ich schätze, dass ich etwa 3-4 Tage Einarbeitung benötige.

Ich melde mich wieder!

von Philipp (Gast)


Lesenswert?

Hi,
echt cooles Projekt, hat soweit erst mal auch gut geklappt. Leider bin 
ich mit der Dauer für solch einen Schreibvorgang noch nicht wirklich 
zufrieden. Dauert schon ne weile, bis man seine Daten auf die SD kriegt. 
Hat da jemand Tipps, wie das vielleicht schneller gehen könnte?

von Johannes (Gast)


Lesenswert?

Hallo,

ich versuche einen Datenlogger mit einem ATmega 8A aufzubauen. Ich habe
mir den Beitrag durchgelesen und den Source-Code angeschaut. Sehr
hilfreich, danke!

Das Beispiel ist mit einem ATmega 8

http://www.mikrocontroller.net/articles/AVR_FAT32#Der_Status

Schaltung aufgebaut wie im Beispiel. Ich habe allerdings einige Probleme
mit dem Code:

Zunächst hatte ich Probleme mit den Timer-Registern, die haben im Code
andere Bezeichnungen als im Datenblatt des ATmega 8 und des 8A. Die habe
ich entsprechend des AVR-Datenblattes angepasst.

Original:

static void timer0_init(){

  TimingDelay = 0;  // initialisierung der zaehl variable

  TCCR0A = 1<<WGM01;     // timer0 im ctc mode
  TIMSK0 = 1<<OCIE0A;    // compare interrupt an

  TCNT0 = START_TCNT;    // ab wo hochgezaehlt wird,
  OCR0A = TOP_OCR;  // maximum bis wo gezaehlt wird bevor compare match

  TCCR0B = PRESCALER;// wenn prescaler gesetzt wird, lauft timer los
  sei();    // interrupts anschalten, wegen compare match
}

Angepasst:

static void timer0_init(){

  TimingDelay = 0;  // initialisierung der zaehl variable

  TCCR1A = (1<<WGM12);     // timer0 im ctc mode
  TIMSK = (1<<OCIE1A);    // compare interrupt an

  TCNT0 = START_TCNT;    // ab wo hochgezaehlt wird,
  OCR1A = TOP_OCR;// maximum bis wo gezaehlt wird bevor compare match

  TCCR1B = PRESCALER;// wenn prescaler gesetzt wird, lauft timer los
  sei();    // interrupts anschalten, wegen compare match
}

Dann bin ich noch total erstaunt, dass der uC mir nur über eine Baudrate
von 600 antwortet, im Quelltext steht doch 9600 ?!? hatte jmd das selbe
Problem?

"// Wenn auf dem terminal "Boot... OK" zu lesen ist, ist Init OK."

Und ich bekomme immer nur "\nBoot" als Antwort, das aber in regelmäßigen
Abständen. Woran kann das liegen, bei euch funktionierts doch überall,
ich habe ja am Quelltext quasi nichts verändert. Hatte es mit drei
verschiedenen SD-Karten probiert, alle standartformatiert, immer mit dem
gleichen Ergebnis.

Hat jmd von euch Erfahrungen mit dem Source-Code "AVR Version 0.6.4" vom
oben Beschriebenen Link?

Ich danke euch im Voraus für eure Antworten.

Grüße

Johannes

von Claudio (Gast)


Lesenswert?

Hallo Johannes

Hast du die clk-div fuse des atmega entfernt bzw. gesetzt?

Denn je nach einstellung, wird der interne/externe clock durch 8 
geteilt.

von Johannes (Gast)


Lesenswert?

Hallo Claudio,

nein ist eigentlich nicht an.

Macht aber auch keinen Sinn. Dann müssten es ja 1200 Baud sein und nicht 
600 Baud (9600 / 8).

von Johannes B. (johannes_jjb)


Lesenswert?

Hallo ich nochmal mit einem Update,

heute habe ich das Ganze nochmal mit einem ATmega 169A probiert.

Habe 1:1 den Quelltext von

http://www.mikrocontroller.net/articles/AVR_FAT32#Einfaches_Code-Beispiel

Aktuellste Version 0.6.4 genommen.  Gleiche Problematik mit der Bautrate 
600 statt 9600 und dass ich nur "\nBoot" empfange.

Ich habe nichts am Quelltext verändert und benutze die 
Beispeilschaltung.

Komisch ...

Bei wem geht die Software denn und was verwendet ihr für eine Hardware?

Grüße

Johannes

von Rolf D. (rolfdegen)


Angehängte Dateien:

Lesenswert?

Hallöchen..

Benutze die Version 6.4. Auf meinem Xmega128A1 funktioniert Lesen und 
Schreiben über SPI mit 8MHz problemlos. Mit 16Mhz SPI Clock laufen 
leider nicht alle SD Karten (Class4). Gibt Fehler bei der 
Initialisierung, könnte vlt. aber am Timer im Xmega liegen. Werde das 
mal überprüfen. Ferner funktioniert der MultiBlock Modus nicht. Habe 
einige Unverständlichkeiten in der Datei "mmc.c" für den MultiBlock 
Zugriff gefunden wzB:
1
// **********************************************************************************************************************************
2
// stop multiblock schreiben
3
// **********************************************************************************************************************************
4
uint8_t mmc_multi_block_stop_write (void){
5
6
  uint8_t cmd[] = {0x40+13,0x00,0x00,0x00,0x00,0xFF};  // CMD13 (send_status), response R2
7
  uint8_t response;
8
9
  mmc_write_byte(0xFD);          // stop token
10
11
  mmc_wait_ready();
12
13
  response=mmc_write_command (cmd);    // cmd13, alles ok?
14
15
  mmc_wait_ready();
16
17
  mmc_disable();
18
  return response;
19
}

Compiler Error: "response=mmc_write_command (cmd);"

Hab diese Zeile ersetzt durch:
spi_write_byte(cmd);
response = spi_read_byte;

Es scheint aber noch mehr Fehler in den Routinen für den MultiBlock 
Zugriff zu geben. Bin auf der Suche..

Gruß Rolf

: Bearbeitet durch User
von Rolf D. (rolfdegen)


Angehängte Dateien:

Lesenswert?

Hallöchen..

Da bin ich nochmal schnell. Der Initialisierungsfehler mit 16MHz SPI 
Clock lag an dem verwendeten Breakout Board für die SD Karte. Da sitzen 
5 Volt Pegelwandler zwischen den Steuerleitungen zur SD Karte um den 
Pegel von 5 Volt auf 3.3 Volt abzusenken. Auf dem Board sitzt ein 
Umschalter für 5 Volt oder 3 Volt Betrieb. Dieser steht bei mir auf 3 
Volt, da ich einen Xmega mit 3.3 Volt Betriebspannung verwende.  Diese 
Pegelwandler scheinen bei 16MHz die Signalflanken der Steuerleitungen zu 
sehr abzuflachen, so dass eine sichere und gute Datenübertragung zur 
oder von der SD Karte nicht mehr gewährleistet ist.

Habe jetzt die Pegelwandler überbrückt, so das die Steuerleitungen 
direkt mit dem Xmega verbunden sind.

Bild: SD Karte Breakout Board

Gruß Rolf

: Bearbeitet durch User
von Rolf D. (rolfdegen)


Lesenswert?

Hallöli..

Hab leider immer noch das Problem das bei MultiBlock Read kein Byte von 
der SD Karte gelesen wird. Das Programm verweilt leider dauerhaft in der 
while Schleife und wartet auf ein zu empfangenes FE Byte. Hab 
verschiedene SDHC Karten (Class4) ausprobiert. Woran könnte es liegen ?
1
// **********************************************************************************************************************************
2
// starten von multi block read. ab sektor addr wird der reihe nach gelesen. also addr++ usw...
3
// **********************************************************************************************************************************
4
uint8_t mmc_multi_block_start_read (uint32_t addr){
5
  
6
  uint8_t cmd[] = {0x40+18,0x00,0x00,0x00,0x00,0xFF};  // CMD18 (read_multiple_block), response R1
7
  uint8_t response;
8
9
  mmc_enable();
10
11
  // addressiertung bei mmc und sd (standart < 2.0) in bytes, also muss sektor auf byte adresse umgerechnet werden.
12
  // sd standart > 2.0, adressierung in sektoren, also 512 byte bloecke
13
  
14
  //if(fat.card_type==0) addr = addr << 9; //addr = addr * 512, nur wenn mmc/sd karte vorliegt
15
  addr = addr << 9;
16
17
  cmd[1] = ((addr & 0xFF000000) >>24 );
18
  cmd[2] = ((addr & 0x00FF0000) >>16 );
19
  cmd[3] = ((addr & 0x0000FF00) >>8 );
20
  cmd[4] = (addr &  0x000000FF);
21
22
  mmc_wait_ready ();
23
24
  spi_write_byte(cmd);    // commando senden und response speichern
25
  response=spi_read_byte();
26
27
  while (spi_read_byte() != 0xFE){    // warten auf start byte
28
    nop();
29
  };
30
31
  return response;
32
}

von Torsten S. (tse)


Lesenswert?

Wenn man die Berichte nur mal überfliegt ist es besser sich nach einer 
Alternative umzusehen die auch das tut was sie soll.

FatFs von ElmChan ist z.B. so eine.

Dem Autor war nicht mal klar was der Unterschied zwischen einer .h und 
.c Datei ist wenn man sich die ersten Posts in diesem Thread anguckt. 
Das spricht Bände.

von Rolf D. (rolfdegen)


Angehängte Dateien:

Lesenswert?

Hallo Torsten

Danke für den Tip. Die Software von ElmChan habe ich mir bereits 
angesehen. Macht einen sehr guten Eindruck. Allerdings müsste ich dafür 
die ganzen Routine in meinem Synth Projekt ändern 
(http://www.cczwei-forum.de/cc2/thread.php?postid=86316#post86316). 
Dafür habe ich aber im Moment keine Zeit. Ferner weis ich nicht, wieviel 
Ram für die Zwischenspeicherung der Daten im Prozessor notwenig ist. 
Muss mit dem Ram sehr sparsam umgehen, da andere  Funktionen in meinem 
Synthesizer auch Speicherplatz beanspruchen.

Mir ist aufgefallen, dass in den Funktionsroutinen 
"mmc_multi_block_start_read" und "mmc_multi_block_read_sector"  beim 
Warten auf das Startbyte nur 0x00 empfangen wird. Wenn ich diese 
Routinen umgehe findet eine Datenübertragung statt. Allerdings sind die 
ersten Bytes nur Müll. Mir scheint es so, das die SD Karte die 
MultiBlock Befehle nicht versteht. Bin aber kein Experte in Bezug auf 
das FAT32 System. Verschiedene aktuelle SD Karten (Class4) habe ich auch 
getestet.

Mir ist auch nicht ganz klar, ob sich der MultiBlock Zugriff in meinem 
Projekt lohnt. Fürs Laden eines Sound Presets von der SD Karte wird 
immer auf eine 32KByte große Binär Datei zugeriffen. Diese Datei 
beinhaltet die Parameter und WAV-Dateinamen für insgesammt 128 Presets 
in einer Sound-Bank. Beim Laden von Sound Samples siehts ein wenig 
anders aus. Ein Wav-File kann die Größe von 1KByte bis 1MByte haben.

Bild 1: Datei und Ordner-System im Synthesizer
Bild 2. Preset Menü


Gruß Rolf

: Bearbeitet durch User
von Moritz Hännes (Gast)


Lesenswert?

Guten Tag,

ich scheitere am versuch die Version 3.1 zu kompelieren, leider bekomme 
ich fünf fehler (alle Fehler sind in der Datei fat-0.3.c):

-conflicting types for 'fat_writeSector'
-conflicting types for 'fat_getNextCluster'
-conflicting types for 'fat_getFreeCluster'
-conflicting types for 'fat_setCluster'
-'superfloppy' undeclared (first use in this function)

ich verwende Atmel Studio 6.2.
Wie könnte ich diese Fehler beheben ?





Grüße

Moritz

von Rolf D. (rolfdegen)


Angehängte Dateien:

Lesenswert?

Hallo Moritz

Ich habe mit der Version 0.6.4 auch Probleme beim kompilieren und bin 
aus diesem Grund wieder zurück auf eine 5er Version glaube ich. Kanns 
leider nicht genau sagen. Im Anhang die kompilierten Dateien. Einfach 
die Dateien in  AVR Studio 6.2 im Solution Explorer als Existen Item 
"adden" bzw laden und kompilieren. Wichtig ist die initialisierung eines 
Timers mit 10ms Interrupt, da sonst zeitkritische Sachen in der SD 
Routine nicht funktionieren. In dem Timer wird die Variable TimingDelay" 
decrementiert.

1
//*************************************************************************
2
// SDCARD Delay Timer 10msec
3
//*************************************************************************
4
ISR (TCD1_OVF_vect)
5
{
6
  TimingDelay = (TimingDelay==0) ? 0 : TimingDelay-1;
7
8
}

Hab dir mal den Source Code drangehangen. die zwei Dateien sd_card.c und 
sd_card.h sind meine Funktionsroutinen im Programm und als Beispiel 
gedacht. Ist aber alles noch etwas konfus. Ich hoffe das hilft dir 
weiter :)

LG Rolf

: Bearbeitet durch User
von holger (Gast)


Lesenswert?

>ich scheitere am versuch die Version 3.1 zu kompelieren,

Was willst du mit diesem uralten Kram? Alle bereits
gefundenen Fehler noch mal suchen? Nimm ne neuere Version
und klopp den Dreck in die Tonne.

von Torsten S. (tse)


Lesenswert?

Etwas drastisch formuliert, aber so ist es.

von Uwe Z. (uwezi)


Lesenswert?

In einem Datenlogger-Projekt habe ich bisher FatFs von ElmChan 
verwendet, der hat aber in der aktuellen Version einige radikale 
Veränderungen bei einigen Funktionsaufrufen vorgenommen und die 
Konfiguration ist dank der vielen Module auch schon immer sehr chaotisch 
gewesen - es ist wohl schwer, eine eierlegende Wollmilchsau auf Dauer am 
Leben zu erhalten.

Hier dagegen läuft die Konfiguration dank einer zentralen .h-Datei sehr 
einfach und problemfrei und ich konnte den Kode direkt und ohne Probleme 
zum Laufen bringen - Version 0.6.1 vom SVN-Server ist zwar 4 Jahre alt, 
ließ sich aber problemlos mit AVR-Studio 6.1 und aktueller Toolchain 
kompilieren.

Testsystem: 3,3V ATmega328P und microSD SDHC von 4GByte und 8GByte.

Der Quellkode selbst ist etwas gewöhnungsbedürftig - bin dabei, den Kode 
etwas aufzuräumen und zu anglifizieren.

 Aber : Bei der Verwendung langer Dateinamen scheint es ein Problem zu 
geben, wenn der lange Dateiname kürzer ist, als ein kurzer Dateiname - 
eine auf diese Weise erstellte Datei hat plötzlich zwei Punkte im 
Dateinamen und läßt sich unter Windows nicht öffnen - da sich das 
vermeiden läßt, habe ich noch nicht nach dem Fehler gesucht...

 Und erst jetzt sehe ich ein, daß die "aktuelle" Version auf dem SVN 
eine uralte Version ist, und man sich wie immer hier im Forum durch 
Gigazeilen von Kommentaren und inkrementellen Änderungen Lesen muß. 
Schade eigentlich. Ich will ja nicht wirklich etwas umsonst und ohne 
Arbeit haben, hatte mich ja schon daran gemacht, die Version 0.6.1 
aufzuräumen, aber das macht dann ja wohl keinen Sinn mehr... Mal sehen, 
och ich Version 0.6.4 ebenfalls direkt und unproblematisch zum Laufen 
bekomme, auch wenn mir der eingeführte 10ms-Timer doch einiges 
Kopfzerbrechen bereitet - abgesehen von Aktivitäten soll mein Logger nur 
einmal pro Sekunde aufwachen, aber das läßt sich sicher irgendwie 
anpassen...

Ich hoffe, ich habe jetzt schließlich die aktuelle Version gefunden...

von Willi Burkhardt (Gast)


Lesenswert?

Hat jemand von Euch erfahrungen mit dieser implementierung gemacht:
https://github.com/BizzaBoy/RFAT

Besonderes Interesse wäre wie "robust" diese Implementierung wirklich 
ist. Der Autor behauptet ja es sei: "100% power fail safe."

von Rolf D. (rolfdegen)


Lesenswert?

Hallöchen..

Ich benutze die aktuelle Version der FAT32 Library.

Ich hab nun folgendes Problem. In einem Ordner befinden sich insgesamt 9 
Dateien. Mit der 'ffrm()' Funktion möchte ich eine Datei aus dieser 
Liste löschen. Leider werden aus der Liste immer 2 Dateien gelöscht.

Z.B. Datei-Liste mit Bezeichnung 1-9. Wenn ich die Datei '3' lösche, 
dann wird die Datei '2' mit gelöscht. Wenn ich Datei '9' lösche, wird 
Datei '8' auch gelöscht. Wenn ich die 1.Datei '1' lösche, wird Datei '2' 
auch gelöscht. Ist nur eine Datei vorhanden und wird diese gelöschr, 
bekomme ich wieder andere Dateien mit 0Byte angezeigt ????


Mein Code:
1
// set folder
2
  ffcd(""); ffcd("SAMPLE");
3
    
4
  // file available ?
5
  if (fat_loadFileDataFromDir(sample_name) == TRUE)
6
  {
7
    // delete file
8
    ffrm(sample_name);
9
    ffclose();
10
  }

Hardware: SDHC Card 4GB SanDisk Fat32 Format
Software: Aktuelle Version FAT32

Schreib- und Lesefunktionen funktionieren problemlos. Nur das löschen 
der Dateien nicht. Kann mir vielleicht jemand helfen. Danke im Voraus.

Gruß Rolf

: Bearbeitet durch User
von Rolf D. (rolfdegen)


Angehängte Dateien:

Lesenswert?

Hallo..

Hier im Forum gabs einen Beitrag von Lukas 
Beitrag "Re: MMC SD library FAT16 FAT32 read write" indem 
er auf einige Fehler in der FAT32 Library hingewiesen hat.

Das Löschen von Dateien funktioniert mit der neuen 'ffrm()' Routine von 
Lukas problemlos.

Im Anhang nochmal die FAT32 Library von Lukas.

Gruß Rolf

: Bearbeitet durch User
von andy (Gast)


Lesenswert?

Hey,

ich hab eine Frage zur "TimeDelay" variable...die wird doch nur 
benötigt, damit man in einem Fehlerfall nicht in einer Endlosschleife 
steckt, oder? D.h. man braucht diese nicht unbedingt im ISR 
dekrementieren. Oder liege ich da falsch?

Frage2: mmc_init()und fat_loadFatData() wird ohne Probleme(return == 
TRUE) ausgeführt. Wenn ich dann eine Datei anlege
1
if (ffopen(fname, 'c') == MMC_FILE_CREATED)
2
{
3
 ffwrites((uint8_t*) "test");
4
 ffwrite(0x0D);
5
}
6
ffclose;
und diese schließe, findet die Funktion ffopen(fname, 'r') die Datei 
nicht.(Fehlercode: MMC_FILE_ERROR)
Hatte jemand evtl. noch dieses Problem?

von Rolf D. (rolfdegen)


Lesenswert?

Hallo Andy,

in der 'mmc_init' wird TimingDelay auch benutzt. Könnte sein, dass deine 
Karten dann nicht mehr richtig initialisiert bzw erkannt werden, wenn du 
es weglässt. Da ich mehrere Timer-Interrupts in meinem Synthesizer 
benutze, habe ich TimingDelay mit integriert.

Ich benutze die letze Version 6.4 Datei Anlegen und Öffnen geht bei mir 
ohne Probleme.


Beispiel:
(die Delays sind nur für die Textmeldungn auf meinem Display notwendig)
1
// save Preset Data ---------------------------------------------------
2
  set_preset_folder();
3
  
4
  // Data.bin file available ?
5
  if (fat_loadFileDataFromDir("Data.bin") == FALSE)
6
  {
7
    fillrectangle(30,38,280,145,color_blue1);
8
    rectangle(33,42,99,243,color_white);
9
    fillrectangle(139,42,180,65,color_blue1);
10
    draw_string("File 'Data.bin' not found!",42,75,6,color_white);
11
    _delay_ms(1000);
12
    if(MMC_FILE_CREATED == ffopen("Data.bin",'c') )
13
    {
14
      draw_string("create new File...",42,90,6,color_white);
15
      _delay_ms(500);
16
      ffwriten(0,0x8000);
17
    }
18
    ffclose();
19
  }
20
21
22
void set_preset_folder(void)
23
{
24
  // set Preset Folder --------------------------------------------------
25
  ffcd("");
26
  ffcd("PRESET");
27
  
28
  // set PRBANK Folder --------------------------------------------------
29
  char folder_temp[9];
30
  strcpy(folder_temp,"PRBANK");
31
  
32
  char xx[3];
33
  sound_bank = sel_sound_bank;
34
35
  itoa(sound_bank,xx,10);
36
  if (sound_bank > 9)
37
  {
38
    strcat(folder_temp,xx);
39
  }
40
  else
41
  {
42
    strcat(folder_temp,"0");
43
    strcat(folder_temp,xx);
44
  }
45
  ffcd(folder_temp);
46
  
47
  // Set SOUND Folder --------------------------------------------------
48
  char folder_temp1[10];
49
  strcpy(folder_temp1,"SOUND");
50
  
51
  char xx1[4];
52
  sound_bank = sel_sound;
53
54
  itoa(sound_bank,xx1,10);
55
  if (sound_bank < 10)
56
  {
57
    strcat(folder_temp1,"00");
58
    strcat(folder_temp1,xx1);
59
  }
60
  else if(sound_bank < 100)
61
  {
62
    strcat(folder_temp1,"0");
63
    strcat(folder_temp1,xx1);
64
  }
65
  else
66
  {
67
    strcat(folder_temp1,xx1);
68
  }
69
  ffcd(folder_temp1);
70
  ffclose();
71
  _delay_ms(100);
72
  
73
}

Gruß Rolf

: Bearbeitet durch User
von Rolf D. (rolfdegen)


Angehängte Dateien:

Lesenswert?

Bezogen auf meinen Beitrag #3769720 vom 19.08.2014 10:27 (etwas weiter 
oben):

Ich habe das Datei System auf der 4GB SD Karte meines Synthesizers 
geändert. Dazu gehört das abspeichern oder löschen von Samples und 
Presets.
Das hört sich jetzt nicht gerade kompliziert an, aber die Arbeit steckt 
mal wieder in den Details. Die Abbildung zeigt die Ordner Stuktur auf 
der SD Karte.

Auf der SD Karte gibt es drei Ordner mit der Bezeichnung PRESET, SAMPLE 
und SYSTEM. Im Ordner 'Preset' sind die gesamten Sound Parameter, 
UserWave-Table und ggf das Sample-File für den Sound abgespeichert. Der 
Ordner 'SAMPLE' beinhaltet die gesamte Sample Library. Hier kann man 
Samples laden, speichern oder löschen, ohne eine Beeinflussung auf die 
Preset Sounds. Dadurch kann man z.B. die komplette Sample Library auf 
der SD Karte ändern oder austauschen, ohne Gefahr zu gehen, dass sich 
die Preset Sounds verändern. Falls ein Preset ein Sample-File besitzt, 
wird dieses immer im Preset Ordner mit abgespeichert.
Im Ordner 'SYSTEM' befinden sich System relevante Daten wzB Bilder, 
Sequenzer-Daten, USERWAVE-Table und die aktuelle Midi CC Tabelle. Die 
USERWAVE-Table besteht aus 128 festen Wellenformen mit 256 Byte Größe 
und kann beliebig ausgetauscht werden. Damit stehen dem Benutzer 
unendlich viele Möglichkeiten der Soundgestaltung zur Verfügung.

Gruß Rolf

: Bearbeitet durch User
von Rolf D. (rolfdegen)


Lesenswert?

andy schrieb:
> Hey,
>
> ich hab eine Frage zur "TimeDelay" variable...die wird doch nur
> benötigt, damit man in einem Fehlerfall nicht in einer Endlosschleife
> steckt, oder? D.h. man braucht diese nicht unbedingt im ISR
> dekrementieren. Oder liege ich da falsch?
>
> Frage2: mmc_init()und fat_loadFatData() wird ohne Probleme(return ==
> TRUE) ausgeführt. Wenn ich dann eine Datei anlege
>
1
if (ffopen(fname, 'c') == MMC_FILE_CREATED)
2
> {
3
>  ffwrites((uint8_t*) "test");
4
>  ffwrite(0x0D);
5
> }
6
> ffclose;
7
>
> und diese schließe, findet die Funktion ffopen(fname, 'r') die Datei
> nicht.(Fehlercode: MMC_FILE_ERROR)
> Hatte jemand evtl. noch dieses Problem?

Hi Andy

Ich glaube ich hatte mal ein ähnliches Problem.
Es könnte noch daran liegen, dass du zuerst einen Ordner anlegen musst 
und dann eine neue Datei in dem Ordner erstellen kannst.

Gruß Rolf

von andy (Gast)


Lesenswert?

Hey Rolf,

danke für deine Antwort. Leider hat es daran nicht gelegen. Habe jetzt 
auch Timingdelay mit eingebaut, hilft auch nichts. Bin immer noch am 
suchen der Lösung. Wenn ich den Fehler finde, melde ich mich ;)

von Rolf D. (rolfdegen)


Angehängte Dateien:

Lesenswert?

Hallo Andy :)

Hier meine kleine Funktionsbibliothek für die SDCARD im Anhang. 
Vieleicht hilft es dir.

Lieben Gruß und guten Rutsch. Rolf

: Bearbeitet durch User
von Torsten S. (tse)


Lesenswert?

Hallo Rolf,

Obwohl diese lib nicht als eine der zuverlässigsten gilt hast Du Dich 
dran gemacht diese benutzbar zu machen - mutig. Und scheinbar tuts die 
auch.

Beim überfliegen des obigen Quelltextes bin ich beeindruckt. Ohne von 
dieser Materie allzuviel zu verstehen kann ich nur ahnen wieviel Arbeit 
da drin steckt. Respekt!

Das einzige was mir nicht gefällt sind die vielen einzelnen 
read_par_value() und write_par_value() Aufrufe. Vielleicht könnte man 
das in ein struct packen und mit einem einfachen memcpy initialisieren 
oder von der Karte lesen.

Einen guten Rutsch,
Torsten

von Nicolai (Gast)


Lesenswert?

Hallo Leute,

erstmal vielen Dank für die Library. Ich wollte einen Datenlogger bauen,
und wenn die mmc_init durchläuft funktioniert alles hervorragend. Nur 
manchmal kommt er nicht durch die prozedur
1
   while (FALSE == mmc_init()){
2
    _delay_ms(100);
3
4
  }

Egal wie lange ich warte, die init läuft nicht durch. Hingegen andere 
male funktioniert es... es scheint ziemlich zufällig zu sein. Außerdem 
habe ich herrausgefunden, dass wenn ich mit meinem Finger den Miso pin 
berühre, dann funktieniert das meistens, kann aber ebenfalls zufall 
sein. Ein Hardreset des controllers hilft auch nicht immer. Wenn Die 
Spannungsversorgung an bleibt und die sd karte einmal initialisiert 
worden ist und man dann den controller resettet, dann geht es fast 
immer. Aber wenn diese wieder ausgeschaltet wurde, dann funktionier das 
weniger oft.

Hatte jemand von euch schonmal solche probleme? Ich bin mittlerweile 
wirklich ratlos.

Grüße

Nicolai


PS: ATMEGA32 16MHZ Quartz SDHC 8GB

von dummy (Gast)


Lesenswert?

>Hatte jemand von euch schonmal solche probleme? Ich bin mittlerweile
>wirklich ratlos.

Mach mal einen Pullup an MISO.

von nicolai (Gast)


Lesenswert?

Hallo,
Der letzte Beitrag ist ja schon etwas her...
ich habe die hardware so aufgebaut wie beschrieben und benutze auch den 
Beispielcode. Leider kommt der Controller fast nie druch die MMC_Init 
funktion.
Ich habe jetzt alle Einträge hier gelesen und auch weitere die man so im 
Internet findet. Leider konnte mir keiner so wirklich helfen. Wenn die 
karte erstmal initialisiert ist funktionier das Schreiben auch 
zuverlässig mehrere Tage lang. Interessanter Weise hängt sich die 
Funtkion wirklich auf...
hat jemand damit schon Erfahrung?

Viele Grüße

Nicolai

von Peter (Gast)


Lesenswert?

Hallo,
ich hoffe hier liest manchmal noch jemand mit. Habe die lib erfolgreich 
zum laufen gebracht. Nur mit neuen SD-karten gibt es auf einmal 
Probleme. Lesen und schreiben klappt nur einmal. Dann kann man zwar die 
geschrieben machen auf dem PC anschauen jedoch nicht auf der MCU. 
Unterscheid zu alten karten ist der "First Physical Sector". Bei den 
altern Karten ist diese immer 1 bei den neuen 8192. Was hat das zu 
bedeuten und kann das mein Problem sein? Wie kann man das lösen?
Grüße Peter

von Peter (Gast)


Lesenswert?

Hallo,
würde eigentlich eine Lösung für das Schreibprobkem bei vollen Clustern 
gefunden?

von Wolfgang (Gast)


Lesenswert?

Das Problem hatte ich vor Jahren gefunden, aber noch keine Lösung. Ich 
verwende die Software bisher in vielen Projekten völlig ohne Probleme. 
Das war nur möglich, weil ich immer nur Klartext an PC zu übertragen 
hatte, da störte es nicht, ein zusätzliches Leerzeichen vor dem 0d0a 
einzufügen, wenn die übertragene Zeichenzahl für diese Zeile ungerade 
war.

Seit der Findung des Problems liegt ein Link zu meiner E-Mail auf diesem 
Beitrag. In den neuen Einträgen war bisher noch kein Lösung des Problems 
dabei.

von Marius (Gast)



Lesenswert?

Hallo,

Seit einiger Zeit versuche ich es diese Bibliotheken einzubinden und zu 
nutzen.

Im konkreten Fall geht es hier um einen Atmega48 der auf eine SD-Karte 
schreiben soll.

Nun bin ich relativ ungeübt, was Bibliotheken einbinden usw angeht, 
sodass ich wahrscheinlich eine deutlich detailliertere Anleitung 
benötige.

Nun zum Eigentlichen Problem:
Ich arbeite derzeit mit Atmel Studio 7. Beim Erstellen eines neuen 
Projektes, füge ich:

fat.c, fat.h
file.c, file.h
mmc.c, mmc.h
mmc_config.h
uart.c, uart.h
hinzu.
Danach bekomme ich diese Fehlermeldungen angezeigt(Im Anhang 
fehlermeldung_anfang_sd)

Dabei ist mir aufgefallen, dass in der mmc.h kein AT_Mega48 enthalten 
ist, weshalb ich den Mega8(der Pingleich ist) kopiert habe und umbenannt 
habe. (Zu sehen in Aenderung1_mmc.h_)
Danach sind mehr Fehlermeldungen aufgetaucht, die so wie es ausschaut, 
viel mit dem UART zu tun haben. (Zu sehen in 
fehlermeldung_nachAenderung1_sd)

Da stellt sich mir die Frage, warum benötige ich diese uart.h überhaupt?

Nun bin ich mir unsicher, ob ich total auf dem Holzweg bin oder mich 
langsam der Lösung des Problems nähere.

Ich würde mich über Antworten sehr freuen.

Mit freundlichem Gruß
Marius

von Stefan F. (Gast)


Lesenswert?

Im Tutorial gibt es das Setting

> #define MMC_SDHC_SUPPORT  TRUE

Aber in den Quelltexten von Version 0.6.4 
(http://www.mikrocontroller.net/attachment/116369/AVR-mmc-0.6.4.zip) 
konnte ich dieses Setting nicht finden.

Ist das Setting überflüssig geworden oder ist der Link zum Download 
nicht mehr aktuell?

von Hau Wech (Gast)


Lesenswert?

Wer Fehlermeldungen des Kompilers bekommt , wie

DECLARATION_AC_POWER_ON_IRGENDWAS undeclared ,

dem fehlen additionelle Header-Files , oder aber hat diese Deklarationen 
in weiteren System-Headern der Compillier-Umgebung schon vorhanden .

Insbesondere wenn die Kompillierumgebung Linux ist , dann werden mit den 
GCC-Bibliotheken und besonders mit dem Linux-Kernel in 
/usr/include/*/linux ständig Deklarationen verändert , ausgelagert in 
andere Header , oder gar vollständig entfernt , oder umbenannt .

Dieser Strang ist schon ca. 10 Jahre alt , und viele Systemheader des 
GNU-Compilers , der C-Bibliotheken und des Linux-Kernels werden sehr 
andersartig aussehen .


Die Kompillierumgebung hat sich sehr verändert , und man müsste sich 
Linux - Betriebssystem e aus alten Zeiten besorgen , um an die Header 
und Fertigkompillierten Bibliotheken zu kommen , die zum Kompillieren 
und Finalem Verlinken bzw. Statischem Einbau nötig sind .

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