Hallo zusammen
Ich verwende ElmChans FatFS (die vollständige Version)
Mit dieser möchte ich mein FlashSpeicher welcher in Form eines ICs
vorhanden ist, ansprechen.
Ich habe die DiskIO inzwischen korrekt angepasst.
Nun geht es darum, den Flash zu formatieren.
Das IC ist intern in Pages zu je 256Bytes aufgeteilt.
Diese kann ich Schreiben und Lesen (in 256Byte Blöcken)
Meine DiskIO Konvertiert die vom FatFS kommenden Anfragen, welche für
einen Sector 512Bytes vorsehen, so dass es diese richtig aus dem Flash
liest.
Nun fehlt bei meinem Flash jedoch eine FAT und auch ein MBR.
Könnte mir jemand helfen, diese beiden zu erstellen?
FatFS bietet zwei Funktionen an:
f_fdisk und f_mkfs
f_mkfs - Create an FAT volume on the logical drive
f_fdisk - Create logical drives on the physical drive
http://elm-chan.org/fsw/ff/00index_e.html
Ich vermute, dass ich zuerst f_fdisk und dann f_mkfs ausführen muss.
Wobei f_fdisk einen MBR voraussetzt.
Bisher habe ich noch keinen MBR selbst gestrickt.
Nach dem Einlesen in Wikipedia, hätte ich den MBR an Adresse 0x00 des
Flashs gelegt. Also aus sicht des FatFS auf Sektor 0
Diesen hätte ich wie im Bild im Anhang erstellt.
Die Partitionstabelle wird ja nach meinem Verständnis mit f_fdisk von
FatFS erstellt.
Müsste das so funktionieren?
Danke
@Holger Krähenbühl (holgerkraehe)
>Ich vermute, dass ich zuerst f_fdisk und dann f_mkfs ausführen muss.>Wobei f_fdisk einen MBR voraussetzt.
Ja.
>Bisher habe ich noch keinen MBR selbst gestrickt.>Nach dem Einlesen in Wikipedia, hätte ich den MBR an Adresse 0x00 des>Flashs gelegt. Also aus sicht des FatFS auf Sektor 0
Ja.
>Die Partitionstabelle wird ja nach meinem Verständnis mit f_fdisk von>FatFS erstellt.
Scheint so.
>Müsste das so funktionieren?
Ja.
Danke für die Antwort.
Tut es jedoch leider nicht.
Habe mir den Code von ElmChan genauer angeschaut.
Das erste wass man nach seinem Tutorial machen soll ist:
/* Register work area (do not care about error) */
f_mount(&fs, "", 0);
/* Create FAT volume with default cluster size */
res = f_mkfs("", 0, 0);
if (res) ...
f_mkfs macht folgendes:
1
if(_MULTI_PARTITION&&part){
2
/* Get partition information from partition table in the MBR */
Er prüft zuerst ob man mehrere Partitionen in den Defines aktiviert hat.
Dies ist standardmässig nicht der Fall und wird auch nicht benötigt.
Falls dies nicht der Fall ist,
geht der Code hier hin:
Hier wird die VolumeSize aus n_vol gebildet.
n_vol ist bei mir: 16755320
Dies bereits nach dem ersten Sprung in f_mkfs
f_mkfs kennt noch einen Übergabeparameter "au"
Dieser definiert die Anzahl Sektoren.
Jedoch können diese nur im Bereich von 0..128 gewählt werden.
Sehr merkwürdig wie ich finde. Denn mein Flash hat 2048 Sektoren a
512Byte
Soll ich nun einfach n_vol manuell setzen?
Was meint ihr?
Du hast da ein bissel schlechte Karten. Der Grund ist, daß Chan's FF
eigentlich zuviel erledigen möchte.
Normalerweise würde man beim Erkennen eines Speichermediums einen
Handler aktivieren, der dieses Medium als solches behandelt, also MBR
ausliest (falls nicht BigFloppy) und dann für jede der 4 möglichen
Partitionen ein dazu passendes Filesystem installiert, welches
wohlgemerkt NUR SEINE Partition behandelt. Bei einer erweiterten
Partition dann wiederum einen Handler, der die log.LW innerhalb dieser
Partition mit passenden Filesystemen verbindet.
Aber:
Chan's FF will das alles selber machen und hat natürlich damit Probleme.
Bedenke mal, was es für Restriktionen auf einer normalen Festplatte
gibt, WO eine Partition losgehen darf. Normalerweise hat man zwischen
MBR und 1. Partition eine Lücke, die bei dir womöglich so groß ist wie
dein Flash. Also kein HD-Layout verwenden, sondern ne große Floppy
emulieren - ohne MBR.
Nochwas:
Chan ist einer der Leute, die unangenehmerweise voraussetzen, daß aller
Speicher im RAM ja grundsätzlich ausgenullt sein muß, weil irgend ein
C-Papst sowas mal vor ... Jahren gelallt hat. Konsequenterweise geht bei
Medienwechsel oder System-Restart oder (vermutlich) beim Umformatieren
und anschließendem Mounten sein FF in den Crash. Ich hatte das mal
behoben durch konsequentes Ablöschen der benötigten RAM-Variablen beim
Mounten, aber die Quellen sind in der Firma..
W.S.
Guten Morgen zusammen
Ich möchte mitteilen, dass ElmChans FatFS erfolgreich für ein FlashChip
angepasst wurde.
Für diejenigen die es interessiert, hier kurz die ToDo Liste:
- Funktionen schreiben, um Pages (Blöcke von Bytes in der Grösse von 512
/ 1024 2048 oder 4096) vom Flash Lesen und Schreiben zu können ab einer
definierten Adresse.
- Dikio.c anpassen.
- FlashChip von FatFS formatieren lassen. mittels f_mkfs
Nun die Details:
Für FatFS ist die kleinste Speichereinheit ein Sektor.
Wie gross ein Sektor ist, wird in ffconf.h definiert.
Standardmässig ist dieser 512Byte. Dies bietet sich bei mir an,
beibehalten zu werden.
1. Niedrigerer Ram verbrauch
2. Meine kleinste physikalisch schreibbare Einheit (auf dem Flash) ist
256Bytes
Nun muss man sich zwei funktionen schreiben, welche vom flash ab einer
bestimmten Addresse Daten lesen und schreiben.
Meine sieht wie folgt aus:
Dies ist die notwendige Grundlage, um in Diskio.c elegant die restlichen
Funktionen zu ergänzen.
In Diskio.c gibt es Read und ein Write.
Diese sehen bei mir so aus:
1
DRESULTdisk_write(
2
BYTEpdrv,/* Physical drive nmuber to identify the drive */
3
constBYTE*buff,/* Data to be written */
4
DWORDsector,/* Sector address in LBA */
5
UINTcount/* Number of sectors to write */
6
)
7
{
8
9
10
11
uint32_tAddress=0;
12
13
//Sektoren addresse,
14
//Sektor wurde mit 512 Byte definiert.
15
16
//Startaddresse berechnen
17
18
19
Address=((sector+1)*512)-512;
20
21
if(count==1)
22
{
23
pageWrite(buff,Address,256);
24
buff+=256;
25
26
pageWrite(buff,Address+256,256);
27
}
28
else
29
{
30
do
31
{
32
//Start Addresse berechnen
33
Address=((sector+1)*512)-512;
34
35
pageWrite(buff,Address,256);
36
buff+=256;
37
38
pageWrite(buff,Address+256,256);
39
buff+=256;
40
sector++;
41
}while(count--);
42
}
43
44
//Warte bis der Schreibvorgang beendet wurde vom Flash
45
while(readStatus()&WIP_MASK);
46
returnRES_OK;
47
48
}
Da ich hier lediglich die Sektoren nummer bekomme, und ein Sektor
512Byte ist, muss ich dies auf meine Gegebenheiten umrechnen.
Insbesondere die Adresse muss entsprechend umgerechnet werden.
Wichtig ist noch die Funktion ioctl in diskio.c
Diese gibt informationen zum Speichermedium an FatFS zurück.
Unteranderem die Anzahl Sektoren und die anzahl Bytes/Sektor
Wobei letzeres ignoriert wird wenn in der config eine fixe Sektoren
grösse definiert wurde (was sinnvoll ist)
1
DRESULTdisk_ioctl(
2
BYTEpdrv,/* Physical drive nmuber (0..) */
3
BYTEcmd,/* Control code */
4
void*buff/* Buffer to send/receive control data */
5
)
6
{
7
8
9
if(cmd==GET_SECTOR_COUNT)
10
{
11
*(DWORD*)buff=2048;//2048 sektoren a 512bytes = 8Mb Flash
12
}
13
14
if(cmd==GET_SECTOR_SIZE)
15
{
16
*(DWORD*)buff=512;
17
}
18
19
if(cmd==GET_BLOCK_SIZE)
20
{
21
*(DWORD*)buff=1;
22
}
23
24
returnRES_OK;
25
26
//return RES_PARERR;
27
}
Wenn man dies ersteinmal angepasst hat, dann kann man den Chip
formatieren.
Dies geschieht mittels dem befehl f_mkfs
1
f_mount(&fs,"",0);
2
res=f_mkfs("",1,0);
Parameter zwei gibt ob eine Partitionstabelle in den MBR geschrieben
wird oder nicht. Da ich auf meinem Speicher keine Partitionen möchte,
wähle ich hier 1 für SFD.
Damit beginnt die FileAllocationTable (FAT) direkt beim ersten Sektor
des Flashchips.
Wenn alles geklappt hat ist res = FR_OK.
Dannach kann man beliebig Dateien erstellen, bearbeiten, löschen etc.
Auch Ordner erstellen und den Inhalt auflisten.
War erst einmal klar, wie das ganze funktioniert, war es sehr einfach
den Code entsprechend anzupassen.
Evtl. hilft es ja jemandem.
Hier noch ein paar Bemerkungen:
- Wearleveling ist nicht vorhanden.
Wenn also oft Dateien erstellt oder geändert werden, wird die FAT sehr
häufig geschrieben. dadurch gehen diese Speicherzellen als erstes
kapput.
Neuere Flashspeicher können mind. 100'000 Schreibzyklen aushalten.
Da kann dann jeder selbst berechnen.
Alternativ könnte man so auch FRAM oder andere Speicher einsetzen.
Viel Spass
Gruss
eure Krähe
Servus,
ich hab das Ganze auf einem W7500P (Cortex M0) laufen. Es gibt da ein
Problem nach dem f_mkfs. Die freien Cluster (f_getfree) werden nach dem
f_mkfs immer konstant angezeigt (max. Größe des NOR Flashs), egal
wieviel ich schreibe. Starte ich das Programm komplett neu (Reset)
stimmt wieder alles und die Größe wird entsprechend angezeigt. So mach
ich das:
FRes = f_getfree ("/", &nclst, &pFatFs); /* Get number of free clusters
on the drive */
FRes = f_mkfs ("", 1, 4096); // sfd filesystem
if (FRes != FR_OK) {
cmd_error(FRes);
}
FRes = f_mount(0, "", 0);
pFatFs = &FatFs;
FRes = f_mount(&FatFs,"/",0);
FRes = f_getfree ("/", &nclst, &pFatFs); /* Get number of free clusters
on the drive */ <-- dieser Wert bleibt konstant bis zum nächsten Rest
Hat jemand eine Idee dazu ?
Gruß
Thomas