www.mikrocontroller.net

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


Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

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

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

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

Autor: Alexander D. (zebprophet)
Datum:

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

Autor: gast (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

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

Autor: Siegmar (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

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

Autor: holger (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: kalhou (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

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

Autor: kalhou (Gast)
Datum:

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

Autor: kalhou (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.
#include <stdlib.h>
#include <string.h>  
#include <avr/io.h>
#include <avr/pgmspace.h>  
#include <avr/interrupt.h>      

#define F_CPU 14745600UL
#include <util/delay.h>

#include "uart-0.1.h"      
#include "mmc-0.2.h"      
#include "fat-0.3.h"      
#include "file-0.3.h"  

#define BUFF_SIZE 15  
unsigned char kb_buffer[BUFF_SIZE];  

int main(void){
  DDRA = 0xFF;
  PORTA = 0x00;

  uinit(); 
      
  uputs("Boot ok\n\r");

  if (mmc_init() == 0){       //ist der Rückgabewert ungleich NULL ist ein Fehler aufgetreten  
  uputs("SD Init ok\n\r");
  } 
  else{
  uputs("SD Init failed\n\r");
  }

  if(0==fat_initfat()){
     uputs("FAT Init ok\n\r");    
   }
  else{
    uputs("FAT Init failed\n\r");
  }

  //Datei lesen
  ffopen('r',"delme.txt");

  uputc(fread());
  uputc(fread());
  uputc(fread());
  uputc(fread());
  uputc(fread());
  uputc(fread());
  uputc(fread());
  uputc(fread());
  uputs("\n\r");
  ffclose();

  for(;;){
    PORTA = 0xFF;
  }
}

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 ;)

Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo,

@ kalhou

also beschreiben einer datei würde wie folgt laufen:

//1
ffopen('w',"DELME   TXT");                      
                               
//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();


-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

Autor: kalhou (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zum Verständniss: verwendet habe ich die aktuellste Version 
"mmc-0.3.1.zip" dort findet sich leider keine Funktion "fat_str"
#include <stdlib.h>
#include <string.h>  
#include <avr/io.h>
#include <avr/pgmspace.h>  
#include <avr/interrupt.h>      

#define F_CPU 14745600UL
#include <util/delay.h>

#include "uart-0.1.h"      
#include "mmc-0.2.h"      
#include "fat-0.3.h"      
#include "file-0.3.h"  

#define BUFF_SIZE 15  
unsigned char kb_buffer[BUFF_SIZE];  

int main(void){
  DDRA = 0xFF;
  PORTA = 0x00;

  uinit(); 
      
  uputs("Boot ok\n\r");

  if (mmc_init() == 0){       //ist der Rückgabewert ungleich NULL ist ein Fehler aufgetreten  
  uputs("SD Init ok\n\r");
  } 
  else{
  uputs("SD Init failed\n\r");
  }

  if(0==fat_initfat()){
     uputs("FAT Init ok\n\r");    
   }
  else{
    uputs("FAT Init failed\n\r");
  }

  //Datei schreiben
  
  //1
  ffopen('w',"DELME   TXT");                      
                               
  //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();


  for(;;){
    PORTA = 0xFF;
  }
}

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 :)

Autor: Daniel R. (zerrome)
Datum:

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

ffwriteString(unsigned char str[],unsigned char name[], unsigned char option){

  ffopen(option,name);                      
  unsigned long int i=0;    


  do{

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

 
  ffclose();
}
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...

Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo,

bei mir gibt es mit folgendem code keine probleme:

  // löscht datei, wenn vorhanden...
  ffrm("DELME   TXT");    
  
  // schreibt in die datei (kann nur schreiben wenn nicht vorhanden ist)
  ffwriteString("das soll in die datei","DELME   TXT",'w'); 

  // anhängen von daten
  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

Autor: kalhou (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: kalhou (Gast)
Datum:

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

Autor: Joachim (Gast)
Datum:

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

Öffnen und nachgucken?

Autor: Kevin Keller (kalhou)
Datum:

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

Autor: holger (Gast)
Datum:

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

Autor: Kevin Keller (kalhou)
Datum:

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

Autor: holger (Gast)
Datum:

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

Autor: tbd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oder id3-tags auslesen ;)

Autor: kalhou (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: kalhou (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: kalhou (Gast)
Datum:

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

Autor: Torsten S. (tse)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Torsten S. (tse)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: kalhou (Gast)
Datum:

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

Autor: Kevin Keller (kalhou)
Datum:
Angehängte Dateien:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Kevin Keller (kalhou)
Datum:

Bewertung
0 lesenswert
nicht 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
extern unsigned char   sector[512];
 vorhanden die immer 512bytes Platz wegnimmt, ob man nun eine Datei 
offen hat, oder nicht..

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Daniel R. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
kann man mit der Lib auch formatieren?

Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo,

nein kann man nicht und wird man auch erstmal nicht.

Autor: G.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Daniel Platte (zerrome)

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

Autor: gast (Gast)
Datum:

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

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

Autor: Siegmar (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"sUpEr Kommentare"

Autor: JoJo (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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



*(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

Autor: Joachim (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

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

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
bug beim leere datei lesen beseitigt.

so das wäre es dann erstmal.

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

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

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
bugfix in ffrm...

Autor: Timo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
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.
temp = ffopen('a',dateiim8.3format);
ffwrite('irgendeinzeichen');
...
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. 
;)

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

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

Autor: Timo (Gast)
Datum:

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

Autor: Lolipop Er (lolipoper)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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:
   if(option=='a' && file_flag==0){
und zwar fehlte die angabe(nach zeile 94):
   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...

Autor: Lolipop Er (lolipoper)
Datum:
Angehängte Dateien:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

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

Autor: Lolipop Er (lolipoper)
Datum:

Bewertung
0 lesenswert
nicht 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:
// External Interrupt 6 service routine                                    
// Interrupt wird ausgelöst, wenn entweder die SD-Karte rausgezogen oder 
// eingesteckt wird. Entsprechend wird SD_ONLINE = 0 gesetzt oder die 
// Initialisierung durchgeführt und SD_ONLINE = 1 gesetzt.
interrupt [EXT_INT6] void ext_int6_isr(void)
{  
  char temp;
  delay_ms(500);    //Warten, bis Karte richtig ein- / ausgesteckt
  if(((SD_Detect)==0)&&(SD_WriteProtect==0)){
        puts1(SDKartegefunden);
        
        puts1(SDInit);
        temp = mmc_init();              
        if(temp==0){
                puts1(OK);     
                puts1(FATInit);
                temp = fat_initfat();                  
                if(temp==0){
                        puts1(OK);
        
                        puts1(messdatatxterstellen);
                        temp = DV_MESSDATATXTerstellen();
                        if(temp==0)puts1(OK);
                        else puts1(Dateibereitsvorhanden); 
                        
                        SD_ONLINE = 1;
                        }    
                 else puts1(Fehler);
        }
        else puts1(Fehler);
  }      
  else {
    puts1(SDKartenichtgefunden);
    SD_ONLINE = 0;
    }
}
dazu die Funktion DV_MESSDATATXTerstellen();
char DV_MESSDATATXTerstellen(){
        char temp=0;                            
        temp = ffopen('w',messdatatxt);
        if(temp==1) return(1);                  //Datei existiert bereits             
        do{   
                ffwrite(messdatatext[temp]);
                temp++;
        }
        while(messdatatext[temp]!='\0');        
        ffclose();
        return(0);   
        }
Diese Funktion wird in der mainloop jede Sekunde aufgerufen:
char DV_MessungSpeichern(int Nummer){
        char temp;
        char TEMP[4]="   ";  
        unsigned long int Abstand; 
        unsigned char Abstand_ASCII[32];
        #asm("cli");
        
        itoa(Nummer,TEMP);
        
        temp = ffopen('a',messdatatxt);
        if(temp==1) return(1);                  //Datei nicht vorhanden
       
        ffwrite('#');                           //Zeilenführungszeichen 
        ffwrite(';');      
        
        ffwrite(TEMP[0]); 
        ffwrite(TEMP[1]); 
        ffwrite(TEMP[2]);
        ffwrite(';');     
        
        ffwrite(Tag_ASCII[0]);
        ffwrite(Tag_ASCII[1]);
        ffwrite('.');       
        ffwrite(Monat_ASCII[0]);
        ffwrite(Monat_ASCII[1]);
        ffwrite('.');         
        ffwrite(Jahr_ASCII[0]);
        ffwrite(Jahr_ASCII[1]);
        ffwrite(Jahr_ASCII[2]);
        ffwrite(Jahr_ASCII[3]);
        ffwrite(';');        
        
        ffwrite(Stunde_ASCII[0]);
        ffwrite(Stunde_ASCII[1]);
        ffwrite(':');  
        ffwrite(Minute_ASCII[0]);
        ffwrite(Minute_ASCII[1]);
        ffwrite(';');  
        ffwrite(';');      
        
        ffwrite('\n');
        ffwrite('\r');
        ffclose();  
        
        #asm("sei"); 
        MessungNr++;
        return(0);   
        }  
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..

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Lolipop Er (lolipoper)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.
 if(SD_ONLINE){ 
        temp = DV_MessungSpeichern(MessungNr);
        }

Ich hab jetzt mal etwas umprogrammiert. Und zwar beim EXTINT6 mit 
einigem Erfolg:
// SD-Card initialisation // FAT-File System initialisation
if(((SD_Detect)==0)&&(SD_WriteProtect==0)){
        puts1(SDKartegefunden);       
        puts1(SDInit);
        temp = mmc_init();              
        if(temp==0){
                puts1(OK);
        
                puts1(FATInit);
                temp = fat_initfat();                  
                if(temp==0){
                        puts1(OK);
                        puts1(messdatatxterstellen);
                        temp = ffopen('r',messdatatxt);
                        ffclose();
                        if(temp==1){
                          DV_MESSDATATXTerstellen();
                          puts1(OK);
                          SD_ONLINE = 1;  
                          }           
                        else puts1(Dateibereitsvorhanden); 
                        }    
                 else puts1(Fehler);
                 }
        else puts1(Fehler);
        }
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..

Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht 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.
if(option=='w' && file_flag==0){  
   if(1==fat_loadFileDataFromDir(name)){
   ...
   ...
   ...
   return(0);
   }
}

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:
char tmp[12];
ultoa(fat.secPerClust,tmp,10);
uputs("secPerClust: ");
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

Autor: Lolipop Er (lolipoper)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht 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
unsigned char ffwrite(unsigned char c){
   unsigned long int clusterOld;
   clusterOld=currentCluster;
   ...
   ...

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

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

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

Autor: Kai Franke (kai-) Benutzerseite
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Lolipop Er (lolipoper)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

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

Autor: Kai Franke (kai-) Benutzerseite
Datum:

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

Autor: Lolipop Er (lolipoper)
Datum:
Angehängte Dateien:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Florian (Gast)
Datum:

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

Was ist da los?

Gruß Flo

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Florian (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hm,
ffopen mit option 'w' gibt auch 1 zurück wenn die datei schon vorhanden 
ist.
versuch mal ein
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...

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Florian (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Florian (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
äh hier auch noch die dateien...

Autor: Alex (Gast)
Datum:

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

Autor: Alex (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Alex (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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) :
#define smallFileSys 0  
#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):
#define smallFileSys 1
#define write 0   

wird der code 8228 bytes groß.

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

wird der code 3618 bytes groß.


güße daniel

Autor: Thomas (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hey,

der ganze Aufruf sieht in etwa so aus:
if( mmc_init() == 0 )
{
    if(0 == fat_initfat())
    {
            //Fat initialisation successful
            LCD1.LCDBuffer[1] = 0 + 48;
            printLCDBufferToGraphic(1);

            unsigned char j = 0;
            unsigned char datei[12]="TEST    PTL";

            // neu erstellen wenn nicht vorhanden und reinscheiben
            if(ffopen('w',datei) == 1)
            {
                ffopen('a',datei);
            }
            for(j=0;j<5;j++)
            {
              ffwrite('b');
            }
            ffclose();
    }
}

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:
#define superfloppy  0
#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.

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

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

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

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
...

Autor: Daniel R. (zerrome)
Datum:

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

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

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke

Werde ich gleich mal ausprobieren.
Gruß Alex

Autor: holger (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also über das makefile oder wie?

bist du Holger Klabunde?

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

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ne hat leider auch nicht funktioniert.

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

Alex

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

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

Autor: zerrome (Gast)
Datum:

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

Autor: Alex (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

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

Autor: holger (Gast)
Datum:

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

Autor: Steffen (Gast)
Datum:

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

Autor: Alex (Gast)
Datum:

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

Autor: zerrome (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Steffen (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
neue version

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

Autor: Michael Z. (incunabulum)
Datum:

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

Autor: Michael Z. (incunabulum)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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:
#include "uart.h"
#define MMC_UART_INIT      uinit
#define MMC_UART_PUTC      uputc
#define MMC_UART_PUTS      uputs
#define MMC_UART_GETC      ugetc
#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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Michael Z. (incunabulum)
Datum:
Angehängte Dateien:

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

Autor: Steffen (Gast)
Datum:

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

Autor: Michael Z. (incunabulum)
Datum:

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

Autor: Steffen (Gast)
Datum:

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

Autor: holger (Gast)
Datum:

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


Das geht auch noch eleganter.

In der Headerdatei:
#define MMC_DEBUG_SECTORS_READ
#define MMC_DEBUG_SECTORS_WRITE

#ifdef MMC_DEBUG_SECTORS_READ
 #define DEBUG_MMC_SECTORS_READ  printf
#else
 #define DEBUG_MMC_SECTORS_READ(...)
#endif

#ifdef MMC_DEBUG_SECTORS_WRITE
 #define DEBUG_MMC_SECTORS_WRITE  printf
#else
 #define DEBUG_MMC_SECTORS_WRITE(...)
#endif


Im C-Code:
...
 DEBUG_MMC_SECTORS_READ("RS %lu 0x%08lX\n",sector,sector);
...

...
 DEBUG_MMC_SECTORS_WRITE("WS %lu 0x%08X\n",sector,sector);
...


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:
//#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");

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Andi (Gast)
Datum:

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

Autor: daniel (Gast)
Datum:

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

Autor: Michael Z. (incunabulum)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Andi S. (laserandi)
Datum:

Bewertung
0 lesenswert
nicht 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:
~/sd_test/main_.c:50: undefined reference to `ffmkdir'
~/sd_test/main_.c:53: undefined reference to `ffmkdir'
~/sd_test/main_.c:68: undefined reference to `ffwrite'
command.o: In function `run_cmd':
~/sd_test/command.c:94: undefined reference to `ffrm'
~/sd_test/command.c:101: undefined reference to `ffmkdir'
~/sd_test/command.c:149: undefined reference to `ffwrite'
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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Martin (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
also du könntest z.B. aus der fat.c direkt die Funktion:
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

Autor: Martin (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Martin (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Martin (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Martin (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Martin (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Martin (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Martin (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Martin (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Martin (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Martin (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Daniel,

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

Klär mich auf!



Gruß Martin

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

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

Autor: Matze Apa (matzeapa)
Datum:

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

Autor: daniel (Gast)
Datum:

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

Autor: Matze Apa (matzeapa)
Datum:

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

Autor: daniel (Gast)
Datum:

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

Autor: Matze Apa (matzeapa)
Datum:

Bewertung
0 lesenswert
nicht 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:
void ffwrites(const char *s )
{
    while (*s) 
      ffwrite(*s++);
}

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

gruß matze

Autor: Martin (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

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

Autor: Matze Apa (matzeapa)
Datum:

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

Autor: daniel (Gast)
Datum:

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

Autor: Matze Apa (matzeapa)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

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

Autor: Matze Apa (matzeapa)
Datum:

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

Autor: daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

also mein hex Editor sagt bei Windows Zeilenumbruch:

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

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

Grüße Daniel

Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Update,
bei Linux ist ein Zeilenumbruch nur 0x0A...

Autor: Chris (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Chris (Gast)
Datum:

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

Gruß
Christian

Autor: Matze Apa (matzeapa)
Datum:

Bewertung
0 lesenswert
nicht 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:
ffzeilenumbruch ()
   {
     ffwrite(0x0D);
     ffwrite(0x0A);
   }

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

Autor: Martin (Gast)
Datum:

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

Autor: C.Alex (Gast)
Datum:

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

Autor: daniel (Gast)
Datum:

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

Autor: C.Alex (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

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

Autor: C.Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
#if (smallFileSys==1)
// *****************************************************************************************************************
// bereitet str so auf, dass man es auf die mmc/sd karte schreiben kann.
// wandelt z.b. "t.txt" -> "T        TXT" oder "main.c" in "MAIN    C  " => also immer 8.3 und upper case letter
// VORSICHT es werden keine Prüfungen gemacht !
// *****************************************************************************************************************
char * fat_str(char *str){
.
.
.
}

#endif

Viele Grüße
C.Alex

Autor: C.Alex (Gast)
Datum:

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

#include <stdlib.h>
#include <avr/io.h>

#include "main.h"
#include "file.h"
#include "fat.h"            
#include "hardware.h"

void beispiele(void);      // kleine datei operations-beispiele

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

  uinit();              // uart initialisierung
 
  uputs((unsigned char*)"\nBoot");

  while (mmc_init() !=0){     //ist der Rückgabewert ungleich NULL ist ein Fehler aufgetreten  
  ;  
  }  
  
  uputs((unsigned char*)"... ");    

  if(0==fat_initfat()){        //ist der Rückgabewert ungleich NULL ist ein Fehler aufgetreten  

   uputs((unsigned char*)"Ok\n");    // wenn auf dem terminal "Boot... OK" zu lesen ist, ist init ok. jetzt kann man schreiben/lesen

    beispiele();                // beispiel 0-4 , da nur atmega8, keine ordner anlegen und ordner rekursiv löschen...
  }


}

// *****************************************************************************************************************
void beispiele(void){

  char datei[12]="test.txt";    // hier muss platz für 11 zeichen sein (8.3), da fat_str diesen string benutzt !!
  fat_str(datei);            // wandelt "test.txt" in das fat format 8.3 der form: "TEST    TXT" muss immer dieses Format haben, auch ordner !!

  // 1.) ______________anlegen und schreiben____________________________________________________________________
  /*   öffnet datei, wenn nicht vorhanden, legt ffopen datei an (rückgabewert = 1 datei existiert, also nur öffnen, 2 = angelegt). */  
  uputc('\n');
  uputs((unsigned char*)"Datei anlegen\n");
  ffopen( datei );            

  /* schreibt string  */
  ffwrites((char*)"Hallo Datei :)");
  // neue zeile in der datei
  ffwrite(0x0D);
  ffwrite(0x0A);

  /* schließt datei */
  ffclose();
  uputs((unsigned char*)"Ende\n");
  
}
//*****************************************************************************************************************


Ich hab doch im Prinzip nichts falsch gemacht? oder?


C.Alex

Autor: Sucher (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Sucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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=322... 
(Thomson)

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

MfG
Achim

Autor: C.Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
.
.
.
char datei[12]="TEST    TXT";
ffrm(datei);
.
.
.

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: C.Alex (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: C.Alex (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: C.Alex (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Johannes Neumann (strangeman)
Datum:

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

Autor: Daniel (Gast)
Datum:

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

Autor: Onit (Gast)
Datum:

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

Autor: Sucher (Gast)
Datum:

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

Autor: Daniel (Gast)
Datum:

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

Autor: Sucher (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Sucher (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Sucher (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Johannes Neumann (strangeman)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

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

Autor: Johannes Neumann (strangeman)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

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

Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wiki auch geupdatet. Vor allem "Interne Technik"

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

Autor: Sucher (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Kricke (Gast)
Datum:

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

Autor: Kricke (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
also besser ist sowas für mmc_init() :
while (mmc_init() !=0){
  ;  
  }  
  

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

Autor: Kricke (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Kricke (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Emperor_L0ser (Gast)
Datum:

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

Autor: daniel (Gast)
Datum:

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

Autor: daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ach äh welche Version benutzt du? 0.5.3 ?

Autor: Emperor_L0ser (Gast)
Datum:

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

Autor: daniel (Gast)
Datum:

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

Autor: Emperor_L0ser (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: elral (Gast)
Datum:

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

Autor: daniel (Gast)
Datum:

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

Autor: elral (Gast)
Datum:

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

Autor: Michael P. (protactinium)
Datum:

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

  //Sektor 0 lesen
  if(0==SDC_Read_Block(SDC_READ_SINGLE_BLOCK, 0, 512))
  {
    vSecOfFirstPartition = (char*)&secOfFirstPartition;
    //Startsektor bestimmen
    *(char*)vSecOfFirstPartition++=fat.sector[454];
    *(char*)vSecOfFirstPartition++=fat.sector[455];
    *(char*)vSecOfFirstPartition++=fat.sector[456];
    *(char*)vSecOfFirstPartition++=fat.sector[457];
    //Prüfung ob man schon im VBR gelesen hat (0x6964654d = Medi)
    if(secOfFirstPartition==0x6964654d)
      return fat_loadFatData(0);  //Superfloppy liegt vor
    else
      //FAT-Daten aus dem ersten Sektor der Partition lesen
      return fat_loadFatData(secOfFirstPartition);
  }
  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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: siegmar (Gast)
Datum:

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

Autor: zerrome (Gast)
Datum:

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

Autor: Michael P. (protactinium)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

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

Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach ja, Wiki auch aktualisiert...

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

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Und hier noch der Wiki Artikel als PDF, zum offline lesen :)

Autor: Steffen K. (steffen3)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Steffen K. (steffen3)
Datum:
Angehängte Dateien:

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

Autor: Daniel R. (zerrome)
Datum:

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

void main(void){
  char tmp[10];

  uinit();

 
  uputs((unsigned char*)"\nBoot");

  while (mmc_init() !=0){ ;}  
  
  uputs((unsigned char*)"... ");    

  fat_loadFatData(0); // läd fat daten

  
  ultoa(fat.rootDir,tmp,10);
  uputs(tmp);      
  uputc(' ');

  utoa(fat.secPerClust,tmp,10);
  uputs(tmp);      

}


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

Autor: Steffen K. (steffen3)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht 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
  //SPI Bus auf max Geschwindigkeit
  SPCR &= ~((1<<SPR0) | (1<<SPR1));
  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

Autor: Steffen K. (steffen3)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schön das es jetzt läuft :)

Autor: Max Power (eizo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Unterstützt das Programm auch Software SPI oder muss man den Hardware 
SPI nutzen?

Autor: Steffen K. (steffen3)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich glaube nur hardware SPI, aber eine software SPI kann man relativ 
leicht implementieren.

Autor: Steffen K. (steffen3)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
ungetest stelle ich hier mal die software SPI rein.

Autor: Steffen K. (steffen3)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Dieses Mal hoffentlich ohne Fehler.

Autor: Johannes Neumann (strangeman)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

unsigned long int seek=file.length;

do{

   code zum lesen...

}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

Autor: Johannes Neumann (strangeman)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: StrangeMan (Gast)
Datum:

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

Autor: Daniel R. (zerrome)
Datum:

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

for(file.seek=0;file.seek<file.length;file.seek++){

//code zum lesen...
//eventuell sogar ffseek() da dies ja file.seek auch updatet...

}


Grüße Daniel

Autor: Johannes Neumann (strangeman)
Datum:
Angehängte Dateien:

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

Autor: Johannes Neumann (strangeman)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ohje, entschuldigt. Die Zeile, in der der Hardware-SPI eingerichtet 
wird, gehört natürlich entfernt. (nach Zeile 50: stattdessen
  #if SPI_Mode

    //Aktiviren des SPI - Bus, Clock = Idel LOW

    //SPI Clock teilen durch 128

    SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1); //Enable SPI, SPI in Master Mode  

  #endif
 einfügen).

Anbei auch noch meine mmc.h. Die Pins habe ich in einer anderen 
headerdatei. Sie sind
#define SD_INSIDE_PORT         PORTA
#define SD_INSIDE_PIN         PINA
#define SD_INSIDE_DDR         DDRA
#define SD_INSIDE_Pin         PA0

#define SD_WRITEPROT_PORT       PORTA
#define SD_WRITEPROT_PIN       PINA
#define SD_WRITEPROT_DDR       DDRA
#define SD_WRITEPROT_Pin       PA2

#define SD_PORT            PORTA
#define SD_P_IN            PINA
#define SD_DDR            DDRA  

#define SD_DI            PA3    
#define SD_DO            PA6    
#define SD_SCK            PA1  
#define SD_SS            PA7

Grüße,
StrangeMan

Autor: FlipFlop (Gast)
Datum:

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

Autor: Johannes Neumann (strangeman)
Datum:

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

//Routine zum Empfangen eines Bytes von der MMC-Karte 

unsigned char mmc_read_byte (void)

//############################################################################

{
  unsigned char Byte = 0;
#if SPI_Mode  //Routine für Hardware SPI
  SPDR = 0xff;
  while(!(SPSR & (1<<SPIF))){};
  Byte = SPDR;

#else      //Routine für Software SPI
  for (unsigned char a=8; a>0; a--) //das Byte wird Bitweise nacheinander Empangen MSB First
    {

    SD_PORT &=~(1<<SD_SCK); //erzeugt ein Clock Impuls (Low) 
    _delay_us(1);
    if (bit_is_set(SD_P_IN,SD_DI) > 0) //Lesen des Pegels von MMC_DI
        {
        Byte |= (1<<(a-1));
        }
      else
        {
        Byte &=~(1<<(a-1));
        }
    SD_PORT |=(1<<SD_SCK); //setzt Clock Impuls wieder auf (High)  
    _delay_us(1);
    }
#endif
  return (Byte);
}


//############################################################################
//Routine zum Senden eines Bytes zur MMC-Karte
void mmc_write_byte (unsigned char Byte)
//############################################################################
{
#if SPI_Mode    //Routine für Hardware SPI
  SPDR = Byte;   //Sendet ein Byte
  while(!(SPSR & (1<<SPIF))) //Wartet bis Byte gesendet wurde
  {
  }
#else      //Routine für Software SPI
  for (unsigned char a=8; a>0; a--) //das Byte wird Bitweise nacheinander Gesendet MSB First
  {
    _delay_us(1);
    if (bit_is_set(Byte,(a-1))>0)  //Ist Bit a in Byte gesetzt
        {
        SD_PORT |= (1<<SD_DO); //Set Output High
        }
      else
        {
        SD_PORT &= ~(1<<SD_DO); //Set Output Low
        }  
    SD_PORT &= ~(1<<SD_SCK);  //erzeugt ein Clock Impuls (LOW)
    _delay_us(1);
    SD_PORT |= (1<<SD_SCK); //setzt Clock Impuls wieder auf (High)
  }
  SD_PORT |= (1<<SD_DO);  //setzt Output wieder auf High  
#endif
}
Ob das Timing so ideal ist, sei dahingestellt. Ich werde nochmal die 
Spezifikationen anschauen, aber das mache ich später.

Danke,
StrangeMan

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

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

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
So,
hier noch die Version als AVR-Studio 4.17 Projekt.

Grüße Daniel

Autor: Michael Z. (incunabulum)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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:
 if(2==ffopen("TEST    TXT")) { ... } 
Hier würde ich mir defines wünschen, die eben diese Statusinformationen 
sprechend bezeichnen. Sowas z. B.
 #define MMC_FILE_NEW 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

Autor: Daniel R. (zerrome)
Datum:

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

Autor: Winne (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie wäre es "True" als Bit  anzulegen

gegebenenfalls mehrere Bitvarriablen/konstanten zu einem Byte zu fassen?

Autor: Michael Z. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
#define UART_INCLUDE  /path/uart.h
#define UART_UPUTS uputs
#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

Autor: Daniel R. (zerrome)
Datum:
Angehängte Dateien:

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

Autor: Michael Z. (incunabulum)
Datum:

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

Autor: Michael M. (mikmik)
Datum:

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

Autor: StrangeMan (Gast)
Datum:

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

Autor: Michael M. (mikmik)
Datum:

Bewertung
0 lesenswert
nicht 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
unsigned char ffexists( unsigned char name[]){
  unsigned char file_flag=fat_loadFileDataFromDir(name);    
  if( file_flag==0 ){return 1;}  //Datei existiert!
else {return 0;}
}

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

have fun,
MM

Autor: Daniel R. (zerrome)
Datum:

Bewertung
0 lesenswert
nicht 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:
unsigned char ffexists( unsigned char name[]){
  return fat_loadFileDataFromDir(name);    
}

Und als Abfrage:
if(TRUE==ffexists((unsigned char*)"MAIN    C  "){

   irgendwas machen
}

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

   irgendwas machen
}

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