SAM4S-EK_FreeRTOS+FAT-SL  1.0
An example project to test the functionality of FreeRTOS+FAT-SL using SD card as data storage medium
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Modules
fat.c
Go to the documentation of this file.
1 /*
2  * FreeRTOS+FAT SL V1.0.1 (C) 2014 HCC Embedded
3  *
4  * The FreeRTOS+FAT SL license terms are different to the FreeRTOS license
5  * terms.
6  *
7  * FreeRTOS+FAT SL uses a dual license model that allows the software to be used
8  * under a standard GPL open source license, or a commercial license. The
9  * standard GPL license (unlike the modified GPL license under which FreeRTOS
10  * itself is distributed) requires that all software statically linked with
11  * FreeRTOS+FAT SL is also distributed under the same GPL V2 license terms.
12  * Details of both license options follow:
13  *
14  * - Open source licensing -
15  * FreeRTOS+FAT SL is a free download and may be used, modified, evaluated and
16  * distributed without charge provided the user adheres to version two of the
17  * GNU General Public License (GPL) and does not remove the copyright notice or
18  * this text. The GPL V2 text is available on the gnu.org web site, and on the
19  * following URL: http://www.FreeRTOS.org/gpl-2.0.txt.
20  *
21  * - Commercial licensing -
22  * Businesses and individuals who for commercial or other reasons cannot comply
23  * with the terms of the GPL V2 license must obtain a commercial license before
24  * incorporating FreeRTOS+FAT SL into proprietary software for distribution in
25  * any form. Commercial licenses can be purchased from
26  * http://shop.freertos.org/fat_sl and do not require any source files to be
27  * changed.
28  *
29  * FreeRTOS+FAT SL is distributed in the hope that it will be useful. You
30  * cannot use FreeRTOS+FAT SL unless you agree that you use the software 'as
31  * is'. FreeRTOS+FAT SL is provided WITHOUT ANY WARRANTY; without even the
32  * implied warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A
33  * PARTICULAR PURPOSE. Real Time Engineers Ltd. and HCC Embedded disclaims all
34  * conditions and terms, be they implied, expressed, or statutory.
35  *
36  * http://www.FreeRTOS.org
37  * http://www.FreeRTOS.org/FreeRTOS-Plus
38  *
39  */
40 #include "../../api/fat_sl.h"
41 
42 #include "fat.h"
43 #include "util.h"
44 #include "volume.h"
45 #include "drv.h"
46 
47 #include "../../version/ver_fat_sl.h"
48 #if VER_FAT_SL_MAJOR != 5 || VER_FAT_SL_MINOR != 2
49  #error Incompatible FAT_SL version number!
50 #endif
51 
52 /****************************************************************************
53  *
54  * _f_writefatsector
55  *
56  * writing fat sector into volume, this function check if fat was modified
57  * and writes data
58  *
59  * RETURNS
60  *
61  * error code or zero if successful
62  *
63  ***************************************************************************/
64 unsigned char _f_writefatsector ( void )
65 {
66  unsigned char a;
67 
68  if ( gl_volume.modified )
69  {
70  unsigned long fatsector = gl_volume.firstfat.sector + gl_volume.fatsector;
71 
73  {
74  return F_ERR_INVALIDSECTOR;
75  }
76 
77  for ( a = 0 ; a < gl_volume.bootrecord.number_of_FATs ; a++ )
78  {
79  unsigned char ret;
80  ret = _f_writeglsector( fatsector );
81  if ( ret )
82  {
83  return ret;
84  }
85 
86  fatsector += gl_volume.firstfat.num;
87  }
88 
89  gl_volume.modified = 0;
90  }
91 
92  return F_NO_ERROR;
93 } /* _f_writefatsector */
94 
95 
96 
97 /****************************************************************************
98  *
99  * _f_getfatsector
100  *
101  * read a fat sector from media
102  *
103  * INPUTS
104  *
105  * sector - which fat sector is needed, this sector number is zero based
106  *
107  * RETURNS
108  *
109  * error code or zero if successful
110  *
111  ***************************************************************************/
112 unsigned char _f_getfatsector ( unsigned long sector )
113 {
114  unsigned char a;
115 
116  if ( gl_volume.fatsector != sector )
117  {
118  unsigned long fatsector;
119 
120  gl_volume.fatsector = sector;
121 
123  {
124  return F_ERR_INVALIDSECTOR;
125  }
126 
128 
129  for ( a = 0 ; a < gl_volume.bootrecord.number_of_FATs ; a++ )
130  {
131  if ( !_f_readglsector( fatsector ) )
132  {
133  return F_NO_ERROR;
134  }
135 
136  fatsector += gl_volume.firstfat.num;
137  }
138 
139  return F_ERR_READ;
140  }
141 
142  return F_NO_ERROR;
143 } /* _f_getfatsector */
144 
145 
146 
147 /****************************************************************************
148  *
149  * _f_setclustervalue
150  *
151  * set a cluster value in the FAT
152  *
153  * INPUTS
154  *
155  * cluster - which cluster's value need to be modified
156  * data - new value of the cluster
157  *
158  * RETURNS
159  *
160  * error code or zero if successful
161  *
162  ***************************************************************************/
163 unsigned char _f_setclustervalue ( unsigned long cluster, unsigned long _tdata )
164 {
165  unsigned char ret;
166 
167  switch ( gl_volume.mediatype )
168  {
169  case F_FAT16_MEDIA:
170  {
171  unsigned long sector = cluster;
172  unsigned short s_data = (unsigned short)( _tdata & 0xffff ); /*keep 16 bit only*/
173 
174  sector /= ( F_SECTOR_SIZE / 2 );
175  cluster -= sector * ( F_SECTOR_SIZE / 2 );
176 
177  ret = _f_getfatsector( sector );
178  if ( ret )
179  {
180  return ret;
181  }
182 
183  if ( _f_getword( &gl_sector[cluster << 1] ) != s_data )
184  {
185  _f_setword( &gl_sector[cluster << 1], s_data );
186  gl_volume.modified = 1;
187  }
188  }
189  break;
190 
191  case F_FAT12_MEDIA:
192  {
193  unsigned char f12new[2];
194  unsigned long sector = cluster;
195  unsigned short pos;
196  unsigned short s_data = (unsigned short)( _tdata & 0x0fff ); /*keep 12 bit only*/
197 
198  if ( cluster & 1 )
199  {
200  s_data <<= 4;
201  }
202 
203  _f_setword( f12new, s_data ); /*create new data*/
204 
205  sector += sector / 2; /*1.5 bytes*/
206  pos = (unsigned short)( sector % F_SECTOR_SIZE );
207  sector /= F_SECTOR_SIZE;
208 
209  ret = _f_getfatsector( sector );
210  if ( ret )
211  {
212  return ret;
213  }
214 
215  if ( cluster & 1 )
216  {
217  f12new[0] |= gl_sector[pos] & 0x0f;
218  }
219 
220  if ( gl_sector[pos] != f12new[0] )
221  {
222  gl_sector[pos] = f12new[0];
223  gl_volume.modified = 1;
224  }
225 
226  pos++;
227  if ( pos >= 512 )
228  {
229  ret = _f_getfatsector( sector + 1 );
230  if ( ret )
231  {
232  return ret;
233  }
234 
235  pos = 0;
236  }
237 
238  if ( !( cluster & 1 ) )
239  {
240  f12new[1] |= gl_sector[pos] & 0xf0;
241  }
242 
243  if ( gl_sector[pos] != f12new[1] )
244  {
245  gl_sector[pos] = f12new[1];
246  gl_volume.modified = 1;
247  }
248  }
249  break;
250 
251  case F_FAT32_MEDIA:
252  {
253  unsigned long sector = cluster;
254  unsigned long oldv;
255 
256  sector /= ( F_SECTOR_SIZE / 4 );
257  cluster -= sector * ( F_SECTOR_SIZE / 4 );
258 
259  ret = _f_getfatsector( sector );
260  if ( ret )
261  {
262  return ret;
263  }
264 
265  oldv = _f_getlong( &gl_sector[cluster << 2] );
266 
267  _tdata &= 0x0fffffff;
268  _tdata |= oldv & 0xf0000000; /*keep 4 top bits*/
269 
270  if ( _tdata != oldv )
271  {
272  _f_setlong( &gl_sector[cluster << 2], _tdata );
273  gl_volume.modified = 1;
274  }
275  }
276  break;
277 
278  default:
279  return F_ERR_INVALIDMEDIA;
280  } /* switch */
281 
282  return F_NO_ERROR;
283 } /* _f_setclustervalue */
284 
285 
286 /****************************************************************************
287  *
288  * _f_getclustervalue
289  *
290  * get a cluster value from FAT
291  *
292  * INPUTS
293  *
294  * cluster - which cluster value is requested
295  * pvalue - where to store data
296  *
297  * RETURNS
298  *
299  * error code or zero if successful
300  *
301  ***************************************************************************/
302 unsigned char _f_getclustervalue ( unsigned long cluster, unsigned long * pvalue )
303 {
304  unsigned long val;
305  unsigned char ret;
306 
307  switch ( gl_volume.mediatype )
308  {
309  case F_FAT16_MEDIA:
310  {
311  unsigned long sector = cluster;
312  sector /= ( F_SECTOR_SIZE / 2 );
313  cluster -= sector * ( F_SECTOR_SIZE / 2 );
314 
315  ret = _f_getfatsector( sector );
316  if ( ret )
317  {
318  return ret;
319  }
320 
321  val = _f_getword( &gl_sector[cluster << 1] );
322  if ( val >= ( F_CLUSTER_RESERVED & 0xffff ) )
323  {
324  val |= 0x0ffff000; /*extends it*/
325  }
326 
327  if ( pvalue )
328  {
329  *pvalue = val;
330  }
331  }
332  break;
333 
334  case F_FAT12_MEDIA:
335  {
336  unsigned char dataf12[2];
337  unsigned long sector = cluster;
338  unsigned short pos;
339 
340  sector += sector / 2; /*1.5 bytes*/
341  pos = (unsigned short)( sector % F_SECTOR_SIZE );
342  sector /= F_SECTOR_SIZE;
343 
344  ret = _f_getfatsector( sector );
345  if ( ret )
346  {
347  return ret;
348  }
349 
350  dataf12[0] = gl_sector[pos++];
351 
352  if ( pos >= 512 )
353  {
354  ret = _f_getfatsector( sector + 1 );
355  if ( ret )
356  {
357  return ret;
358  }
359 
360  pos = 0;
361  }
362 
363  dataf12[1] = gl_sector[pos];
364 
365  val = _f_getword( dataf12 );
366 
367  if ( cluster & 1 )
368  {
369  val = val >> 4;
370  }
371  else
372  {
373  val = val & 0xfff;
374  }
375 
376  if ( val >= ( F_CLUSTER_RESERVED & 0xfff ) )
377  {
378  val |= 0x0ffff000; /*extends it*/
379  }
380 
381  if ( pvalue )
382  {
383  *pvalue = val;
384  }
385  }
386  break;
387 
388  case F_FAT32_MEDIA:
389  {
390  unsigned long sector = cluster;
391  sector /= ( F_SECTOR_SIZE / 4 );
392  cluster -= sector * ( F_SECTOR_SIZE / 4 );
393 
394  ret = _f_getfatsector( sector );
395  if ( ret )
396  {
397  return ret;
398  }
399 
400  if ( pvalue )
401  {
402  *pvalue = _f_getlong( &gl_sector[cluster << 2] ) & 0x0fffffff; /*28bit*/
403  }
404  }
405  break;
406 
407  default:
408  return F_ERR_INVALIDMEDIA;
409  } /* switch */
410 
411  return F_NO_ERROR;
412 } /* _f_getclustervalue */
413 
414 
415 
416 
417 
418 
419 /****************************************************************************
420  *
421  * _f_clustertopos
422  *
423  * convert a cluster position into physical sector position
424  *
425  * INPUTS
426  *
427  * cluster - original cluster position
428  * pos - position structure to fills the position
429  *
430  ***************************************************************************/
431 void _f_clustertopos ( unsigned long cluster, F_POS * pos )
432 {
433  pos->cluster = cluster;
434 
435  if ( !cluster )
436  {
437  pos->sector = gl_volume.root.sector;
438  pos->sectorend = pos->sector + gl_volume.root.num;
439  }
440  else
441  {
442  unsigned long sectorcou = gl_volume.bootrecord.sector_per_cluster;
443  pos->sector = ( pos->cluster - 2 ) * sectorcou + gl_volume._tdata.sector;
444  pos->sectorend = pos->sector + sectorcou;
445  }
446 
447  if ( cluster >= F_CLUSTER_RESERVED )
448  {
449  pos->sectorend = 0;
450  }
451 
452  pos->pos = 0;
453 } /* _f_clustertopos */
454 
455 
456 
457 
458 /****************************************************************************
459  *
460  * _f_getcurrsector
461  *
462  * read current sector according in file structure
463  *
464  * INPUTS
465  * f - internal file pointer
466  *
467  * RETURNS
468  * error code or zero if successful
469  *
470  ***************************************************************************/
471 unsigned char _f_getcurrsector ( void )
472 {
473  unsigned char ret;
474  unsigned long cluster;
475 
477  {
478  gl_volume.fatsector = (unsigned long)-1;
479  ret = _f_getclustervalue( gl_file.pos.cluster, &cluster );
480  if ( ret )
481  {
482  return ret;
483  }
484 
485  if ( cluster >= F_CLUSTER_RESERVED )
486  {
487  return F_ERR_EOF;
488  }
489 
490  _f_clustertopos( cluster, &gl_file.pos );
491  }
492 
493  return _f_readglsector( gl_file.pos.sector );
494 } /* _f_getcurrsector */
495 
496 
497 
498 /****************************************************************************
499  *
500  * _f_alloccluster
501  *
502  * allocate cluster from FAT
503  *
504  * INPUTS
505  * pcluster - where to store the allocated cluster number
506  *
507  * RETURNS
508  *
509  * error code or zero if successful
510  *
511  ***************************************************************************/
512 unsigned char _f_alloccluster ( unsigned long * pcluster )
513 {
514  unsigned long maxcluster = gl_volume.maxcluster;
515  unsigned long cou;
516  unsigned long cluster = gl_volume.lastalloccluster;
517  unsigned long value;
518  unsigned char ret;
519 
520  for ( cou = 0 ; cou < maxcluster ; cou++ )
521  {
522  if ( cluster >= maxcluster )
523  {
524  cluster = 0;
525  }
526 
527  ret = _f_getclustervalue( cluster, &value );
528  if ( ret )
529  {
530  return ret;
531  }
532 
533  if ( !value )
534  {
535  gl_volume.lastalloccluster = cluster + 1; /*set next one*/
536  *pcluster = cluster;
537 
538  return F_NO_ERROR;
539  }
540 
541  cluster++;
542  }
543 
544  return F_ERR_NOMOREENTRY;
545 } /* _f_alloccluster */
546 
547 
548 
549 
550 /****************************************************************************
551  *
552  * _f_removechain
553  *
554  * remove cluster chain from fat
555  *
556  * INPUTS
557  * cluster - first cluster in the cluster chain
558  *
559  * RETURNS
560  *
561  * error code or zero if successful
562  *
563  ***************************************************************************/
564 unsigned char _f_removechain ( unsigned long cluster )
565 {
566  gl_volume.fatsector = (unsigned long)-1;
567 
568  if ( cluster < gl_volume.lastalloccluster ) /*this could be the begining of alloc*/
569  {
570  gl_volume.lastalloccluster = cluster;
571  }
572 
573  while ( cluster < F_CLUSTER_RESERVED && cluster >= 2 )
574  {
575  unsigned long nextcluster;
576 
577  unsigned char ret = _f_getclustervalue( cluster, &nextcluster );
578  if ( ret )
579  {
580  return ret;
581  }
582 
583  ret = _f_setclustervalue( cluster, F_CLUSTER_FREE );
584  if ( ret )
585  {
586  return ret;
587  }
588 
589  cluster = nextcluster;
590  }
591 
592  return _f_writefatsector();
593 } /* _f_removechain */
594 
595 
596 
597 
unsigned char _f_removechain(unsigned long cluster)
Definition: fat.c:564
unsigned long sector
Definition: volume.h:70
unsigned char modified
Definition: volume.h:87
unsigned char _f_writefatsector(void)
Definition: fat.c:64
F_FILE gl_file
Definition: volume.c:61
F_SECTOR firstfat
Definition: volume.h:79
unsigned long fatsector
Definition: volume.h:84
void _f_setlong(void *, unsigned long)
Definition: util.c:144
unsigned long pos
Definition: fat_sl.h:70
F_BOOTRECORD bootrecord
Definition: volume.h:78
unsigned char sector_per_cluster
Definition: volume.h:58
unsigned char _f_alloccluster(unsigned long *pcluster)
Definition: fat.c:512
void _f_clustertopos(unsigned long cluster, F_POS *pos)
Definition: fat.c:431
unsigned long _f_getlong(void *)
Definition: util.c:116
unsigned long lastalloccluster
Definition: volume.h:86
unsigned char _f_getcurrsector(void)
Definition: fat.c:471
unsigned long sectorend
Definition: fat_sl.h:69
unsigned char _f_writeglsector(unsigned long sector)
Definition: drv.c:96
unsigned short _f_getword(void *)
Definition: util.c:68
void _f_setword(void *, unsigned short)
Definition: util.c:92
unsigned char mediatype
Definition: volume.h:89
#define F_SECTOR_SIZE
Definition: config_fat_sl.h:57
Definition: fat_sl.h:65
unsigned char _f_getfatsector(unsigned long sector)
Definition: fat.c:112
F_SECTOR _tdata
Definition: volume.h:81
unsigned long sector
Definition: fat_sl.h:68
F_POS pos
Definition: fat_sl.h:116
unsigned long num
Definition: volume.h:71
F_SECTOR root
Definition: volume.h:80
F_VOLUME gl_volume
Definition: volume.c:60
unsigned long maxcluster
Definition: volume.h:90
unsigned char number_of_FATs
Definition: volume.h:59
#define F_CLUSTER_FREE
Definition: fat_sl.h:97
unsigned char _f_readglsector(unsigned long sector)
Definition: drv.c:178
char gl_sector[F_SECTOR_SIZE]
Definition: volume.c:62
#define F_CLUSTER_RESERVED
Definition: fat_sl.h:98
unsigned char _f_getclustervalue(unsigned long cluster, unsigned long *pvalue)
Definition: fat.c:302
unsigned long cluster
Definition: fat_sl.h:67
unsigned char _f_setclustervalue(unsigned long cluster, unsigned long _tdata)
Definition: fat.c:163