⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fs_fat.c

📁 keil arm flash fs 最新版 在Keil arm下使用
💻 C
📖 第 1 页 / 共 5 页
字号:
/*----------------------------------------------------------------------------
 *      R T L  -  F l a s h   F i l e   S y s t e m
 *----------------------------------------------------------------------------
 *      Name:    FS_FAT.C 
 *      Purpose: FAT File System Class Implementation
 *      Rev.:    V3.22
 *----------------------------------------------------------------------------
 *      This code is part of the RealView Run-Time Library.
 *      Copyright (c) 2004-2008 KEIL - An ARM Company. All rights reserved.
 *---------------------------------------------------------------------------*/

#include "File_Config.h"
#include <string.h>

#define INVAL_SECT  0xFFFFFFFF

/* Possible "search_for_name" function actions definitions */
#define ACT_NONE    0x00
#define ACT_KEEPFCB 0x01

/* Local Constants */
static const DEVPAR IniDevCfg[10] = {
/*  FatType  SecClus  SecClus32 NumHeads  BootRecSec */
  { FS_FAT12,    16,       0,        2,        65 },      /* Size   8 MB */
  { FS_FAT12,    16,       0,        2,        65 },      /* Size  16 MB */
  { FS_FAT12,    32,       0,        2,        65 },      /* Size  32 MB */
  { FS_FAT12,    32,       0,        4,        65 },      /* Size  64 MB */
  { FS_FAT16,    16,       0,        8,        65 },      /* Size 128 MB */
  { FS_FAT16,    16,       4,       16,       129 },      /* Size 256 MB */
  { FS_FAT16,    32,       8,       32,       129 },      /* Size 512 MB */
  { FS_FAT16,    32,      16,       64,       257 },      /* Size   1 GB */
  { FS_FAT16,    64,      32,      128,       257 },      /* Size   2 GB */
  { FS_FAT32,    64,      64,      128,       257 }};     /* Size   4 GB */
/* Parameters in this table are optimized for SD/MMC memory cards.            */
/* Optimal file system is FAT12/FAT16 with Cluster sizes 8k, 16k, 32k.        */
/* Cluster 2 shall be block aligned (32K aligned)                             */

static const U8 ChIndex[13] = { 1, 3, 5, 7, 9, 14, 16, 18, 20, 22, 24, 28, 30 };

/* Local Variables */
static FCACHE  fat;
static DCACHE  ca;
static FATINFO mmc;
static U32 free_clus;
static U32 top_clus;
static U32 startDirClus;
static U32 firstEntClus;
static U16 firstEntOffs;
static U8  numOfEntries;
static BIT in_root_1x;
static BIT warm_restart;

static char name_buf[260];              /* Name buffer */

/* Local Function Prototypes */
static int  init_dev          (void);
static BOOL write_mbr         (U32 iSz);
static BOOL write_br          (U32 sernum);
static void wipe_disk         (U32 dsize);
static BOOL fat_find_dir      (const char *fn, IOB *fcb, U8 create);
static BOOL write_label       (const char *label);
static BOOL set_next_clus     (U32 *ptr_clus);
static BOOL get_free_clus     (U32 *ptr_clus);
static BOOL clus_in_use       (U32 clus);
static BOOL clear_clus        (U32 clus);
static BOOL write_fat_link    (U32 clus, U32 next_clus);
static BOOL unlink_clus_chain (U32 clus);
static BOOL alloc_new_clus    (U32 *ptr_clus, U8 wr_fat_link);
static U32  count_free_clus   (void);
static U32  clus_to_sect      (U32 clus);
static U32  get_fat_sect      (U32 clus);
static BOOL read_sector       (U32 sect);
static BOOL write_sector      (U32 sect);
static BOOL read_cache        (U32 sect, U32 cnt);
static void write_cache       (U32 sect);
static BOOL cache_fat         (U32 sect);
static BOOL is_EOC            (U32 clus);
static U32  get_EOC           (void);
static BOOL get_mbrec         (void);
static BOOL get_bootrec       (void);
static BOOL is_fat_valid      (void);
static U16  get_time          (void);
static U16  get_date          (void);
static void set_time_date     (FINFO *info, FILEREC *frec);
static BOOL cvt_fatname       (const char *fn, char *en);
static BOOL check_lfn         (const char *fn);
static U8   val_char          (U8 ch);
static BOOL val_char_sn       (U8 ch);
//static BOOL val_char_ln     (U8 ch);
static U8   val_char_lab      (U8 ch);
static U16  get_u16           (U8 *nr);
static void set_u16           (U8 *nr, U16 val);
static U32  get_u32           (U8 *nr);
static void set_u32           (U8 *nr, U32 val);
static BOOL get_dir_name      (const char *fn, char *dn, unsigned int *sz);
static BOOL get_nt_name       (const char *fn, char *sn, int num);
static U32  get_dir_sect      (U32 clus);
static BOOL search_for_name   (const char *name, IOB *fcb, U8 type, U8 keep_fcb);
static BOOL find_name         (const char *name, IOB *fcb, U8 type);
static BOOL check_name        (const char *name, IOB *fcb, U8 type);
static BOOL alloc_name        (const char *name, IOB *fcb);
static BOOL get_next_info     (FINFO *info, IOB *fcb);
static BOOL chk_dir_empty     (IOB *fcb);
static BOOL read_last_entry   (IOB *fcb, FILEREC *filerec);
static BOOL write_last_entry  (IOB *fcb, FILEREC *filerec);
static BOOL write_entries     (const char *name, IOB *fcb, U8 type, FILEREC *last_entry);
static BOOL delete_entries    (IOB *fcb, U8 action);
static BOOL rename_entries    (const char *new_name, IOB *fcb, U8 type);
static BOOL write_dot_entries (IOB *fcb);
static U8   lfn_calc_chksum   (U8 *fn);
static void lfn_copy_name     (U8 *lfn, char *fn);
static BOOL lfn_cmp_name      (U8 *lfn, char *fn);
static BOOL sfn_cmp_name      (U8 *sfn, char *fn);
static void lfn_copy_info     (S8 *fn, U8 *lfn);
static BOOL chk_param         (const char *par, const char *sp);

/*--------------------------- fat_init --------------------------------------*/

int fat_init (void) {
   /* Initialize FAT File System driver. */

   /* Initialize Flash Card interface. */
   if (mmc_init () == __FALSE) {
      /* Failed to Initialize or No Card error. */
      return (1);
   }
   /* Initialize FAT file system. */
   return (init_dev ());
}


/*--------------------------- init_dev --------------------------------------*/

static int init_dev (void) {
   U32 root_scnt;

   /* Invalidate Cached Sectors. */
   fat.sect = INVAL_SECT;
   fat.buf  = (U8 *)&mc_cache[0];
   fat.dirty= __FALSE;

   ca.sect  = INVAL_SECT;
   ca.buf   = (U8 *)&mc_cache[128];
   ca.cbuf  = (U8 *)&mc_cache[256];
   ca.nwr   = 0;
   ca.nrd   = 0;

   /* First 2 clusters are always reserved. */
   top_clus = 2;

   /* Clear MMC info record. */
   memset (&mmc, 0, sizeof (mmc));

   if (get_mbrec () == __FALSE) {
      /* Failed to read or invalid MBR. */
      warm_restart = __FALSE;
      return (2);
   }

   /* Read Boot Record Info. */
   if (get_bootrec () == __FALSE) {
      /* Failed to read or Invalid Boot Record. */
      warm_restart = __FALSE;
      return (3);
   }

   if (is_fat_valid () == __FALSE) {
      /* Invalid FAT table. */
      warm_restart = __FALSE;
      return (4);
   }

   /* Calculate Root Sector Count. */
   root_scnt = (mmc.RootEntCnt * 32 + mmc.BytesPerSec - 1) / mmc.BytesPerSec;

   /* Count Data Sectors/Clusters */
   mmc.DataSecCnt  = mmc.DskSize - (mmc.RsvdSecCnt + 
                                    mmc.NumOfFat * mmc.FatSize + root_scnt);
   mmc.DataClusCnt = mmc.DataSecCnt / mmc.SecPerClus;
   mmc.RootDirAddr = mmc.RsvdSecCnt + mmc.NumOfFat * mmc.FatSize;
   mmc.RootSecCnt  = root_scnt;
   mmc.ClusSize    = mmc.SecPerClus * mmc.BytesPerSec;
   mmc.EntsPerClus = mmc.ClusSize / 32;

   /* Determine Fat Type. */
   if (mmc.DataClusCnt < 4085) {
      mmc.FatType = FS_FAT12;
      warm_restart = __FALSE;
   }
   else if (mmc.DataClusCnt < 65525) {
      mmc.FatType = FS_FAT16;
      warm_restart = __FALSE;
   }
   else {
      mmc.FatType = FS_FAT32;
      /* Calculate number of free cluster the first time. */
      if (warm_restart == __FALSE) {
         warm_restart = __TRUE;
         free_clus = count_free_clus ();
      }
   }

   return (0);
}


/*--------------------------- fat_format ------------------------------------*/

BOOL fat_format (const char *label) {
   /* Format a Flash Card for FAT12 or FAT16. */
   U32 datSect,volSz,iSz,secClus,i,sec;
   MMCFG mcfg;

   /* Read MMC/SD Card configuration. */
   if (mmc_read_config (&mcfg) == __FALSE) {
      /* Failed to read Card configuration. */
      return (__FALSE);
   }

   /* Check Read and Write Block sizes. */
   if (mcfg.read_blen != mcfg.write_blen) {
      return (__FALSE);
   }
   switch (mcfg.read_blen) {
      case 512:
         /* Up to 1GB cards. */
         break;

      case 1024:
         /* 2 GB cards. */
         mcfg.blocknr *= 2;
         break;

      case 2048:
         /* 4 GB cards. */
         mcfg.blocknr *= 4;
         break;

      default:
         /* Block Size not supported. */
         return (__FALSE);
   }

   volSz = mcfg.blocknr >> 11;
   for (iSz = 0, i = 8; iSz < 10; i <<= 1, iSz++) {
      if (volSz < i) break;
   }
   if (iSz == 10) {
      /* Only Flash Card up to 4GB supported. */
      return (__FALSE);
   }

   /* Check for parameter: /WIPE */
   if (chk_param ("WIPE", label) == __TRUE) {
      /* Clear the whole disk. */
      wipe_disk (mcfg.blocknr);
   }

   /* Format with Partition Table and BPB. */
   mmc.BootRecSec = IniDevCfg[iSz].BootRecSec;
   mmc.DskSize    = mcfg.blocknr - mmc.BootRecSec;
   mmc.RsvdSecCnt = 1;
   mmc.BytesPerSec= 512;
   mmc.NumOfFat   = 2;

   /* Set Volume Parameter Info. */
   mmc.FatType    = IniDevCfg[iSz].FatType;
   secClus        = IniDevCfg[iSz].SecClus;

   /* Check for parameter: /FAT32 */
   if (chk_param ("FAT32", label) == __TRUE) {
      /* Force FAT32 */
      mmc.FatType = FS_FAT32;
      secClus     = IniDevCfg[iSz].SecClus32;
      if (secClus == 0) {
         /* Not possible to use FAT32, size is too small. */
         return (__FALSE);
      }
   }

   mmc.SecPerClus = secClus;
   mmc.ClusSize   = secClus * 512;

   datSect = mmc.DskSize - mmc.RsvdSecCnt;
   /* Calculate Data Space and FAT Table Size. */
   switch (mmc.FatType) {
      case FS_FAT12:
         datSect -= 32;
         mmc.RootEntCnt  = 512;
         mmc.RootSecCnt  = 32;
         mmc.DataClusCnt = (datSect * 512 - 1022) / (secClus * 512 + 3);
         mmc.FatSize     = (mmc.DataClusCnt * 3 + 1022) / 1024;
         break;
      case FS_FAT16:
         datSect -= 32;
         mmc.RootEntCnt  = 512;
         mmc.RootSecCnt  = 32;
         mmc.DataClusCnt = (datSect * 128 - 255) / (secClus * 128 + 1);
         mmc.FatSize     = (mmc.DataClusCnt + 255) / 256;
         break;
      case FS_FAT32:
         mmc.RootSecCnt  = 0;
         mmc.DataClusCnt = (datSect * 64 - 127) / (secClus * 64 + 1);
         mmc.FatSize     = (mmc.DataClusCnt + 127) / 128;
         break;
   }

   /* Count Data Sectors/Clusters */
   mmc.DataSecCnt  = mmc.DskSize - (mmc.RsvdSecCnt + mmc.RootSecCnt +
                                    mmc.NumOfFat * mmc.FatSize);
   mmc.RootDirAddr = mmc.RsvdSecCnt + mmc.NumOfFat * mmc.FatSize;

   /* 2nd Cluster should be 32K aligned for optimal Card performance. */
   sec = mmc.RootDirAddr + mmc.RootSecCnt;
   mmc.BootRecSec = ((mmc.BootRecSec + sec + 32) & ~0x3F) - sec;

   warm_restart = __FALSE;
   /* Write MBR, create Partition Table. */
   if (write_mbr (iSz) == __FALSE) {
      return (__FALSE);
   }

   /* Generate Boot Record  */
   if (write_br (mcfg.sernum) == __FALSE) {
      return (__FALSE);
   }

   /* Clear FAT Table and Root Directory. */
   memset (ca.buf, 0, 512);

   /* Write Reserved Clusters 0,1 to FAT table. */
   switch (mmc.FatType) {
      case FS_FAT12:
         set_u32 (&ca.buf[0], 0xFFFFF8);
         break;
      case FS_FAT16:
         set_u32 (&ca.buf[0], 0xFFFFFFF8);
         break;
      case FS_FAT32:
         /* Write also Root Dir Cluster to FAT table. */
         set_u32 (&ca.buf[0], 0x0FFFFFF8);
         set_u32 (&ca.buf[4], 0xFFFFFFFF);
         set_u32 (&ca.buf[8], 0x0FFFFFFF);
         break;
   }
   sec = mmc.BootRecSec + mmc.RsvdSecCnt;
   /* Use cache for faster write. */
   write_cache (sec);
   memset (ca.buf, 0, 12);

   datSect = mmc.RootSecCnt;
   if (mmc.FatType == FS_FAT32) {
      /* Clear first Data Cluster (Root Dir) for FAT32. */
      datSect = mmc.SecPerClus;
   }
   datSect += mmc.FatSize * 2;

   for (i = 1; i < datSect; i++) {
      write_cache (sec + i);
   }
   /* Flush the cache when done. */
   write_cache (0);

   if (*label != 0) {
      /* If provided, write also a Volume Label. */
      return (write_label (label));
   }
   return (__TRUE);
}


/*--------------------------- write_mbr -------------------------------------*/

static BOOL write_mbr (U32 iSz) {
   /* Construct and write a Master Boot Record to sector 0. */
   U8  NumHeads;
   U32 val;

   memset (ca.buf, 0, 512);

   NumHeads = IniDevCfg[iSz].NumHeads;
   /* Boot Descriptor: Non Bootable Device. */
   ca.buf[446] = 0;

   /* Beginning of Partition - Head */
   ca.buf[447] = mmc.BootRecSec / 32;

   /* First Partition Cylinder/Sector */
   val = mmc.BootRecSec % 32;
   set_u16 (&ca.buf[448], val + 1);

   /* File System Descriptor. */
   switch (mmc.FatType) {
      case FS_FAT12:
         /* Type 12-bit FAT */
         ca.buf[450] = 0x01;
         break;
      case FS_FAT16:
         if (iSz < 3) {
            /* Type 16-bit FAT, Partition < 32 MB */
            ca.buf[450] = 0x04;
         }
         else {
            /* Type 16-bit FAT, Partition > 32MB */
            ca.buf[450] = 0x06;
         }
         break;
      case FS_FAT32:
            /* Type 32-bit FAT, Partition < 2047GB */
         ca.buf[450] = 0x0b;
         break;
   }

   /* End of Partition - Head */
   ca.buf[451] = NumHeads;

   /* End of Partition Cylinder/Sector. */
   val = (mmc.DskSize + mmc.BootRecSec) / (2 * NumHeads);
   set_u16 (&ca.buf[452], val | 32);

   /* First Sector Position Relative to Beginning of Device. */
   set_u32 (&ca.buf[454], mmc.BootRecSec);

   /* Number of Sectors in Partition */
   set_u32 (&ca.buf[458], mmc.DskSize);

   /* Executable Marker */
   set_u16 (&ca.buf[510], 0xAA55);
   return (write_sector (0));
}


/*--------------------------- write_br --------------------------------------*/

static BOOL write_br (U32 sernum) {
   /* Construct and write a Boot Rrecord. */

   memset (ca.buf, 0, 512);

   /* Boot Code: E9 00 90 */
   ca.buf[0] = 0xE9;
   ca.buf[1] = 0x00;
   ca.buf[2] = 0x90;

   /* OEM name */
   memcpy (&ca.buf[3], "MSWIN4.1", 8);

   /* Bytes per Sector */
   set_u16 (&ca.buf[11], 512);

   /* Sectors per Cluster */
   ca.buf[13] = mmc.SecPerClus;

   /* Reserved Sectors */
   ca.buf[14] = mmc.RsvdSecCnt;

   /* Number of FAT Tables */
   ca.buf[16] = 2;

   /* Root Entry Count */
   if (mmc.FatType != FS_FAT32) {
      /* Must be 0 for FAT32. */
      set_u16 (&ca.buf[17], 512);
   }

   /* Total Sector Count */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -