1 | /*#######################################################################################
|
2 | FAT for AVR (MMC/SD)
|
3 |
|
4 | Copyright (C) 2004 Ulrich Radig
|
5 |
|
6 | Bei Fragen und Verbesserungen wendet euch per EMail an
|
7 |
|
8 | mail@ulrichradig.de
|
9 |
|
10 | oder im Forum meiner Web Page : www.ulrichradig.de
|
11 |
|
12 |
|
13 | Dieses Programm ist freie Software. Sie können es unter den Bedingungen der
|
14 | GNU General Public License, wie von der Free Software Foundation veröffentlicht,
|
15 | weitergeben und/oder modifizieren, entweder gemäß Version 2 der Lizenz oder
|
16 | (nach Ihrer Option) jeder späteren Version.
|
17 |
|
18 | Die Veröffentlichung dieses Programms erfolgt in der Hoffnung,
|
19 | daß es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE,
|
20 | sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT
|
21 | FÜR EINEN BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License.
|
22 |
|
23 | Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
|
24 | Programm erhalten haben.
|
25 | Falls nicht, schreiben Sie an die Free Software Foundation,
|
26 | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
27 | #######################################################################################*/
|
28 |
|
29 | #include "fat.h"
|
30 |
|
31 | unsigned char cluster_size;
|
32 | unsigned int fat_offset;
|
33 | unsigned int cluster_offset;
|
34 | unsigned int volume_boot_record_addr;
|
35 |
|
36 | //############################################################################
|
37 | //Auslesen Cluster Size der MMC/SD Karte und Speichern der größe ins EEprom
|
38 | //Auslesen Cluster Offset der MMC/SD Karte und Speichern der größe ins EEprom
|
39 | void fat_init (void)
|
40 | //############################################################################
|
41 | {
|
42 | struct BootSec *bootp; //Zeiger auf Bootsektor Struktur
|
43 |
|
44 | unsigned char Buffer[BlockSize];
|
45 |
|
46 | //volume_boot_record_addr = fat_addr (Buffer);
|
47 | mmc_read_sector (MASTER_BOOT_RECORD,Buffer); //Read Master Boot Record
|
48 | if (Buffer[510] == 0x55 && Buffer[511] == 0xAA)
|
49 | {
|
50 | FAT_DEBUG("\r\nMBR Signatur found!\r\n");
|
51 | }
|
52 | else
|
53 | {
|
54 | FAT_DEBUG("\r\nMBR Signatur not found!\r\n");
|
55 | while(1);;
|
56 | }
|
57 |
|
58 |
|
59 | volume_boot_record_addr = Buffer[VBR_ADDR] + (Buffer[VBR_ADDR+1] << 8);
|
60 |
|
61 | mmc_read_sector (volume_boot_record_addr,Buffer);
|
62 | if (Buffer[510] == 0x55 && Buffer[511] == 0xAA)
|
63 | {
|
64 | FAT_DEBUG("\r\nVBR Signatur found!\r\n");
|
65 | }
|
66 | else
|
67 | {
|
68 | FAT_DEBUG("\r\nVBR Signatur not found!\r\n");
|
69 | volume_boot_record_addr = MASTER_BOOT_RECORD;//<- added by Hennie
|
70 | mmc_read_sector (MASTER_BOOT_RECORD,Buffer); //Read Master Boot Record
|
71 | }
|
72 |
|
73 | bootp=(struct BootSec *)Buffer;
|
74 | cluster_size = bootp->BPB_SecPerClus;
|
75 | fat_offset = bootp->BPB_RsvdSecCnt;
|
76 |
|
77 | cluster_offset = ((bootp->BPB_BytesPerSec * 32)/BlockSize);
|
78 | cluster_offset += fat_root_dir_addr(Buffer);
|
79 | }
|
80 |
|
81 | //############################################################################
|
82 | //Auslesen der Adresse des First Root Directory von Volume Boot Record
|
83 | unsigned int fat_root_dir_addr (unsigned char *Buffer)
|
84 | //############################################################################
|
85 | {
|
86 | struct BootSec *bootp; //Zeiger auf Bootsektor Struktur
|
87 | unsigned int FirstRootDirSecNum;
|
88 | //auslesen des Volume Boot Record von der MMC/SD Karte
|
89 | mmc_read_sector (volume_boot_record_addr,Buffer);
|
90 | bootp=(struct BootSec *)Buffer;
|
91 |
|
92 | //berechnet den ersten Sector des Root Directory
|
93 | FirstRootDirSecNum = ( bootp->BPB_RsvdSecCnt +
|
94 | (bootp->BPB_NumFATs * bootp->BPB_FATSz16));
|
95 |
|
96 | FirstRootDirSecNum+= volume_boot_record_addr;
|
97 |
|
98 | return(FirstRootDirSecNum);
|
99 | }
|
100 |
|
101 | //############################################################################
|
102 | // Ausgabe des angegebenen Directory Eintrag in Entry_Count
|
103 | // ist kein Eintrag vorhanden, ist der Eintrag im
|
104 | // Rückgabe Cluster 0xFFFF. Es wird immer nur ein Eintrag ausgegeben
|
105 | // um Speicherplatz zu sparen um es auch für kleine Atmels zu benutzen
|
106 | unsigned int fat_read_dir_ent (unsigned int dir_cluster, //Angabe Dir Cluster
|
107 | unsigned char Entry_Count, //Angabe welcher Direintrag
|
108 | unsigned long *Size, //Rückgabe der File Größe
|
109 | unsigned char *Dir_Attrib, //Rückgabe des Dir Attributs
|
110 | unsigned char *Buffer) //Working Buffer
|
111 | //############################################################################
|
112 | {
|
113 | unsigned char *pointer;
|
114 | unsigned int TMP_Entry_Count = 0;
|
115 | unsigned long Block = 0;
|
116 | struct DirEntry *dir; //Zeiger auf einen Verzeichniseintrag
|
117 |
|
118 | pointer = Buffer;
|
119 |
|
120 | if (dir_cluster == 0)
|
121 | {
|
122 | Block = fat_root_dir_addr(Buffer);
|
123 | }
|
124 | else
|
125 | {
|
126 | //Berechnung des Blocks aus BlockCount und Cluster aus FATTabelle
|
127 | //Berechnung welcher Cluster zu laden ist
|
128 | //Auslesen der FAT - Tabelle
|
129 | fat_load (dir_cluster,&Block,Buffer);
|
130 | Block = ((Block-2) * cluster_size) + cluster_offset;
|
131 | }
|
132 |
|
133 | //auslesen des gesamten Root Directory
|
134 | for (unsigned int blk = Block;;blk++)
|
135 | {
|
136 | mmc_read_sector (blk,Buffer); //Lesen eines Blocks des Root Directory
|
137 | for (unsigned int a=0;a<BlockSize; a = a + 32)
|
138 | {
|
139 | dir=(struct DirEntry *)&Buffer[a]; //Zeiger auf aktuellen Verzeichniseintrag holen
|
140 |
|
141 | if (dir->DIR_Name[0] == 0) //Kein weiterer Eintrag wenn erstes Zeichen des Namens 0 ist
|
142 | {
|
143 | return (0xFFFF);
|
144 | }
|
145 |
|
146 | //Prüfen ob es ein 8.3 Eintrag ist
|
147 | //Das ist der Fall wenn es sich nicht um einen Eintrag für lange Dateinamen
|
148 | //oder um einen als gelöscht markierten Eintrag handelt.
|
149 | if ((dir->DIR_Attr != ATTR_LONG_NAME) &&
|
150 | (dir->DIR_Name[0] != DIR_ENTRY_IS_FREE))
|
151 | {
|
152 | //Ist es der gewünschte Verzeichniseintrag
|
153 | if (TMP_Entry_Count == Entry_Count)
|
154 | {
|
155 | //Speichern des Verzeichnis Eintrages in den Rückgabe Buffer
|
156 | for(unsigned char b=0;b<11;b++)
|
157 | {
|
158 | if (dir->DIR_Name[b] != SPACE)
|
159 | {
|
160 | if (b == 8)
|
161 | {
|
162 | *pointer++= '.';
|
163 | }
|
164 | *pointer++=dir->DIR_Name[b];
|
165 | }
|
166 | }
|
167 | *pointer++='\0';
|
168 | *Dir_Attrib = dir->DIR_Attr;
|
169 |
|
170 | //Speichern der Filegröße
|
171 | *Size=dir->DIR_FileSize;
|
172 |
|
173 | //Speichern des Clusters des Verzeichniseintrages
|
174 | dir_cluster = dir->DIR_FstClusLO;
|
175 |
|
176 | //Eintrag gefunden Rücksprung mit Cluster File Start
|
177 | return(dir_cluster);
|
178 | }
|
179 | TMP_Entry_Count++;
|
180 | }
|
181 | }
|
182 | }
|
183 | return (0xFFFF); //Kein Eintrag mehr gefunden Rücksprung mit 0xFFFF
|
184 | }
|
185 |
|
186 | //############################################################################
|
187 | // Auslesen der Cluster für ein File aus der FAT
|
188 | // in den Buffer(512Byte). Bei einer 128MB MMC/SD
|
189 | // Karte ist die Cluster größe normalerweise 16KB groß
|
190 | // das bedeutet das File kann max. 4MByte groß sein.
|
191 | // Bei größeren Files muß der Buffer größer definiert
|
192 | // werden! (Ready)
|
193 | // Cluster = Start Clusterangabe aus dem Directory
|
194 | void fat_load ( unsigned int Cluster, //Angabe Startcluster
|
195 | unsigned long *Block,
|
196 | unsigned char *TMP_Buffer) //Workingbuffer
|
197 | //############################################################################
|
198 | {
|
199 | //Zum Überprüfen ob der FAT Block schon geladen wurde
|
200 | unsigned int FAT_Block_Store = 0;
|
201 |
|
202 | //Byte Adresse innerhalb des Fat Blocks
|
203 | unsigned int FAT_Byte_Addresse;
|
204 |
|
205 | //FAT Block Adresse
|
206 | unsigned int FAT_Block_Addresse;
|
207 |
|
208 | //Berechnung für den ersten FAT Block (FAT Start Addresse)
|
209 | for (unsigned int a = 0;;a++)
|
210 | {
|
211 | if (a == *Block)
|
212 | {
|
213 | *Block = (0x0000FFFF & Cluster);
|
214 | return;
|
215 | }
|
216 |
|
217 | if (Cluster == 0xFFFF)
|
218 | {
|
219 | break; //Ist das Ende des Files erreicht Schleife beenden
|
220 | }
|
221 | //Berechnung des Bytes innerhalb des FAT BlockŽs
|
222 | FAT_Byte_Addresse = (Cluster*2) % BlockSize;
|
223 |
|
224 | //Berechnung des Blocks der gelesen werden muß
|
225 | FAT_Block_Addresse = ((Cluster*2) / BlockSize) +
|
226 | volume_boot_record_addr + fat_offset;
|
227 | //Lesen des FAT Blocks
|
228 | //Überprüfung ob dieser Block schon gelesen wurde
|
229 | if (FAT_Block_Addresse != FAT_Block_Store)
|
230 | {
|
231 | FAT_Block_Store = FAT_Block_Addresse;
|
232 | //Lesen des FAT Blocks
|
233 | mmc_read_sector (FAT_Block_Addresse,TMP_Buffer);
|
234 | }
|
235 |
|
236 | //Lesen der nächsten Clusternummer
|
237 | Cluster = (TMP_Buffer[FAT_Byte_Addresse + 1] << 8) +
|
238 | TMP_Buffer[FAT_Byte_Addresse];
|
239 | }
|
240 | return;
|
241 | }
|
242 |
|
243 | //############################################################################
|
244 | //Lesen eines 512Bytes Blocks von einem File
|
245 | void fat_read_file (unsigned int Cluster,//Angabe des Startclusters vom File
|
246 | unsigned char *Buffer, //Workingbuffer
|
247 | unsigned long BlockCount) //Angabe welcher Bock vom File geladen
|
248 | //werden soll a 512 Bytes
|
249 | //############################################################################
|
250 | {
|
251 | //Berechnung des Blocks aus BlockCount und Cluster aus FATTabelle
|
252 | //Berechnung welcher Cluster zu laden ist
|
253 |
|
254 | unsigned long Block = (BlockCount/cluster_size);
|
255 |
|
256 | //Auslesen der FAT - Tabelle
|
257 | fat_load (Cluster,&Block,Buffer);
|
258 | Block = ((Block-2) * cluster_size) + cluster_offset;
|
259 | //Berechnung des Blocks innerhalb des Cluster
|
260 | Block += (BlockCount % cluster_size);
|
261 | //Read Data Block from Device
|
262 | mmc_read_sector (Block,Buffer);
|
263 | return;
|
264 | }
|
265 |
|
266 | //############################################################################
|
267 | //Lesen eines 512Bytes Blocks von einem File
|
268 | void fat_write_file (unsigned int cluster,//Angabe des Startclusters vom File
|
269 | unsigned char *buffer, //Workingbuffer
|
270 | unsigned long blockCount) //Angabe welcher Bock vom File gespeichert
|
271 | //werden soll a 512 Bytes
|
272 | //############################################################################
|
273 | {
|
274 | //Berechnung des Blocks aus BlockCount und Cluster aus FATTabelle
|
275 | //Berechnung welcher Cluster zu speichern ist
|
276 | unsigned char tmp_buffer[513];
|
277 | unsigned long block = (blockCount/cluster_size);
|
278 |
|
279 | //Auslesen der FAT - Tabelle
|
280 | fat_load (cluster,&block,tmp_buffer);
|
281 | block = ((block-2) * cluster_size) + cluster_offset;
|
282 | //Berechnung des Blocks innerhalb des Cluster
|
283 | block += (blockCount % cluster_size);
|
284 | //Write Data Block to Device
|
285 | mmc_write_sector (block,buffer);
|
286 | return;
|
287 | }
|
288 |
|
289 | //####################################################################################
|
290 | //Sucht ein File im Directory
|
291 | unsigned char fat_search_file (unsigned char *File_Name, //Name des zu suchenden Files
|
292 | unsigned int *Cluster, //Angabe Dir Cluster welches
|
293 | //durchsucht werden soll
|
294 | //und Rückgabe des clusters
|
295 | //vom File welches gefunden
|
296 | //wurde
|
297 | unsigned long *Size, //Rückgabe der File Größe
|
298 | unsigned char *Dir_Attrib,//Rückgabe des Dir Attributs
|
299 | unsigned char *Buffer) //Working Buffer
|
300 | //####################################################################################
|
301 | {
|
302 | unsigned int Dir_Cluster_Store = *Cluster;
|
303 | for (unsigned char a = 0;a < 100;a++)
|
304 | {
|
305 | *Cluster = fat_read_dir_ent(Dir_Cluster_Store,a,Size,Dir_Attrib,Buffer);
|
306 | if (*Cluster == 0xffff)
|
307 | {
|
308 | return(0); //File not Found
|
309 | }
|
310 | if(strcasecmp((char *)File_Name,(char *)Buffer) == 0)
|
311 | {
|
312 | return(1); //File Found
|
313 | }
|
314 | }
|
315 | return(2); //Error
|
316 | }
|