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

📄 fs_fat.c

📁 keil arm flash fs 最新版 在Keil arm下使用
💻 C
📖 第 1 页 / 共 5 页
字号:
      sect = get_fat_sect (2);
      cache_fat (sect);
      for (clus = 2; clus < (mmc.DataClusCnt + 2); clus++) {
         if ((clus & 0xFF) == 0) {
            /* Read a part of FAT table to buffer. */
            cache_fat (sect++);
         }
         /* if 'next' == 0 (LE or BE) */
         if (((U16 *)fat.buf)[clus & 0xFF] == 0) {
            nfree++;
         }
      }
      return (nfree);
   }
   if (mmc.FatType == FS_FAT32) {
      sect = get_fat_sect (2);
      cache_fat (sect);
      for (clus = 2; clus < (mmc.DataClusCnt + 2); clus++) {
         if ((clus & 0x7F) == 0) {
            /* Read a part of FAT table to buffer. */
            cache_fat (sect++);
         }
         /* if 'next' == 0 (LE or BE) */
         if (((U32 *)fat.buf)[clus & 0x7F] == 0) {
            nfree++;
         }
      }
      return (nfree);
   }
   return (0);
}


/*--------------------------- clus_to_sect ----------------------------------*/

static U32 clus_to_sect (U32 clus) {
   /* Calculate absolute sector address from the cluster index. */
   U32 sect,base;

   base = mmc.BootRecSec + mmc.RootDirAddr;
   if (mmc.FatType != FS_FAT32) {
      base += mmc.RootSecCnt;
   }
   sect = (clus - 2) * mmc.SecPerClus;
   return (base + sect);
}


/*--------------------------- get_fat_sect ----------------------------------*/

static U32 get_fat_sect (U32 clus) {
   /* Calculate absolute FAT Sector address from cluster address. */
   U32 fats;

   switch (mmc.FatType) {
      case FS_FAT12:
         /* FAT Cluster width 12 bits. */
         fats = (clus * 3) / 1024;
         break;

      case FS_FAT16:
         /* FAT Cluster width 16 bits. */
         fats = clus / 256;
         break;

      case FS_FAT32:
         /* FAT Cluster width 32 bits. */
         fats = clus / 128;
         break;

      default:
         /* Not supported. */
         return (0);
   }
   if (fats >= mmc.FatSize) {
      return (0);
   }
   fats += (mmc.BootRecSec + mmc.RsvdSecCnt);
   return (fats);
}


/*--------------------------- read_sector -----------------------------------*/

static BOOL read_sector (U32 sect) {
   /* Read a 512 byte sector from Flash Card. */

   if (sect == ca.sect) {
      /* Required sector already in buffer. */
      return (__TRUE);
   }

   if (sect >= ca.csect && sect < (ca.csect + ca.nwr)) {
      /* This sector is in write cache buffer. */
      memcpy (ca.buf, ca.cbuf + (sect - ca.csect) * 512, 512);
      ca.sect = sect;
      return (__TRUE);
   }

   /* Sector not in cache, read it from the Memory Card. */
   if (mmc_read_sect (sect, ca.buf, 1) == __TRUE) {
      ca.sect = sect;
      return (__TRUE);
   }
   ca.sect = INVAL_SECT;
   return (__FALSE);
}


/*--------------------------- write_sector ----------------------------------*/

static BOOL write_sector (U32 sect) {
   /* Write a 512 byte sector to Flash Card. */

   if (mmc_write_sect (sect, ca.buf, 1) == __TRUE) {
      ca.sect = sect;
      return (__TRUE);
   }
   return (__FALSE);
}


/*--------------------------- read_cache ------------------------------------*/

static BOOL read_cache (U32 sect, U32 cnt) {
   /* Read a 512 byte sector from Flash Card. */

   if ((_MC_CSIZE == 0) || (ca.nwr > 0)) {
      /* File Caching switched off or write caching active. */
      return (read_sector (sect));
   }

   if (ca.nrd > 0) {
      if ((ca.csect <= sect) && sect < (ca.csect + ca.nrd)) {
         /* Requested sector is already cached. */
         memcpy (ca.buf, ca.cbuf + (sect - ca.csect) * 512, 512);
         ca.sect = sect;
         return (__TRUE);
      }
   }

   if (cnt > _MC_CSIZE) {
      cnt = _MC_CSIZE;
   }

   /* Sector not in cache, read it from the Memory Card. */
   if (mmc_read_sect (sect, ca.buf, cnt) == __TRUE) {
      ca.sect  = sect;
      /* First sector is used, the rest is cached. */
      ca.csect = sect + 1;
      ca.nrd   = cnt - 1;
      return (__TRUE);
   }
   ca.sect = INVAL_SECT;
   ca.nrd  = 0;
   return (__FALSE);
}


/*--------------------------- write_cache -----------------------------------*/

static void write_cache (U32 sect) {
   /* Write a 512 byte sector to Data cache. */

   if (_MC_CSIZE == 0) {
      /* File Caching switched off. */
      if (sect) {
         write_sector (sect);
      }
      return;
   }
   if (sect == 0) {
      /* Flush cache request. */
      if (ca.nwr) {
         mmc_write_sect (ca.csect, ca.cbuf, ca.nwr);
         ca.nwr = 0;
      }
      return;
   }
   ca.sect = sect;
   if (ca.nwr > 0) {
      if (sect == (ca.csect + ca.nwr) && ca.nwr < _MC_CSIZE) {
         /* Next sector is continuous, still space in cache. */
         memcpy (ca.cbuf + (ca.nwr * 512), ca.buf, 512);
         ca.nwr++;
         return;
      }
      /* Not continuous sector or buffer full, flush the cache. */
      mmc_write_sect (ca.csect, ca.cbuf, ca.nwr);
      ca.nwr = 0;
   }
   /* Write Data cache is empty. */
   memcpy (ca.cbuf, ca.buf, 512);
   ca.csect = sect;
   ca.nwr   = 1;
   ca.nrd   = 0;
}


/*--------------------------- cache_fat -------------------------------------*/

static BOOL cache_fat (U32 sect) {
   /* Handle MC FAT Cache. Read/write a 512 byte FAT sector. */

   if (sect == fat.sect) {
      /* Required sector already in buffer. */
      return (__TRUE);
   }
   if (fat.dirty == __TRUE) {
      /* Current FAT sector has been changed, write it first. */
      fat.dirty = __FALSE;
      mmc_write_sect (fat.sect, fat.buf, 1);
   }
   if (sect == 0) {
      /* Only write if sector updated. */
      return (__TRUE);
   }
   if (mmc_read_sect (sect, fat.buf, 1) == __TRUE) {
      fat.sect = sect;
      return (__TRUE);
   }
   fat.sect = INVAL_SECT;
   return (__FALSE);
}


/*--------------------------- is_EOC ----------------------------------------*/

static BOOL is_EOC (U32 clus) {
   /* Check if this cluster is an End Of Chain Marker. */

   switch (mmc.FatType) {
      case FS_FAT12:
         if (clus >= 0x0FF8) {
            return (__TRUE);
         }
         break;
      case FS_FAT16:
         if (clus >= 0xFFF8) {
            return (__TRUE);
         }
         break;
      case FS_FAT32:
         if ((clus & 0x0FFFFFFF) >= 0x0FFFFFF8) {
            return (__TRUE);
         }
         break;
   }
   return (__FALSE);
}


/*--------------------------- get_EOC ---------------------------------------*/

static U32 get_EOC (void) {
   /* Return an End Of Chain Marker. */

   switch (mmc.FatType) {
      case FS_FAT12:
         return (0x0FFF);
      case FS_FAT16:
         return (0xFFFF);
      case FS_FAT32:
         return (0x0FFFFFFF);
   }
   return (0);
}


/*--------------------------- get_mbrec -------------------------------------*/

static BOOL get_mbrec (void) {
   /* Read Master Volume Boot Record info. */

   /* Read MBR and set FAT offset address. */
   if (read_sector (0) == __FALSE) {
      return (__FALSE);
   }

   /* Check Executable Marker. */
   if (get_u16 (&ca.buf[510]) != 0xAA55) {
      /* Invalid Master Boot Record. */
      return (__FALSE);
   }

   if ((ca.buf[0] == 0xE9) || (ca.buf[0] == 0xEB && ca.buf[2] == 0x90)) {
      /* Partition Table does not exist, this is a BPB. */
      mmc.BootRecSec = 0;
   }
   else {
      /* Flash Cards have only one Partition. */
      mmc.BootRecSec = get_u32 (&ca.buf[454]);
   }
   return (__TRUE);
}


/*--------------------------- get_bootrec -----------------------------------*/

static BOOL get_bootrec (void) {
   /* Read Volume Boot Record info. */

   if (read_sector (mmc.BootRecSec) == __FALSE) {
      return (__FALSE);
   }
   /* Check Executable Marker. */
   if (get_u16 (&ca.buf[510]) != 0xAA55) {
      /* Invalid Master Boot Record. */
      return (__FALSE);
   }
   /* Set Volume Parameter Info. */
   mmc.SecPerClus = ca.buf[13];
   mmc.BytesPerSec= get_u16 (&ca.buf[11]);
   mmc.RsvdSecCnt = get_u16 (&ca.buf[14]);
   mmc.NumOfFat   = ca.buf[16];
   mmc.RootEntCnt = get_u16 (&ca.buf[17]);
   mmc.DskSize    = get_u16 (&ca.buf[19]);
   mmc.FatSize    = get_u16 (&ca.buf[22]);

   if ((mmc.DskSize == 0) && (mmc.FatSize == 0)) {
      /* Read or correct specific data in mmc structure for FAT32. */
      mmc.FAT32_ExtFlags  = get_u16 (&ca.buf[40]);
      mmc.FAT32_RootClus  = get_u32 (&ca.buf[44]);
      mmc.FAT32_FSInfo    = get_u16 (&ca.buf[48]);
      mmc.FAT32_BkBootSec = get_u16 (&ca.buf[50]);
   }

   if (mmc.DskSize == 0) {
      /* If num of sectors > 0xFFFF, this field is nonzero. */
      mmc.DskSize = get_u32 (&ca.buf[32]);
   }

   if (mmc.FatSize == 0) {
      /* Fat size is in this field for FAT32. */
      mmc.FatSize = get_u32 (&ca.buf[36]);
   }

   return (__TRUE);
}


/*--------------------------- is_fat_valid ----------------------------------*/

static BOOL is_fat_valid (void) {
   /* Check if Volume Info is sane. */

   /* We only support 512 byte sectors. */
   if (mmc.BytesPerSec != 512) {
      return (__FALSE);
   }
   /* Check for Valid Sectors per Cluster values. */
   switch (mmc.SecPerClus) {
      case 1:
      case 2:
      case 4:
      case 8:
      case 16:
      case 32:
      case 64: break;
      default: return (__FALSE);
   }
   /* There should be at least 1 reserved sector. */
   if (mmc.RsvdSecCnt == 0 || mmc.RsvdSecCnt > 64) {
      return (__FALSE);
   }
   /* Only 1 or 2 FAT tables supported. */
   switch (mmc.NumOfFat) {
      case 1:
      case 2:  break;
      default: return (__FALSE);
   }
   if (mmc.FatSize > mmc.DskSize) {
      return (__FALSE);
   }
   return (__TRUE);
}


/*--------------------------- get_time --------------------------------------*/

static U16 get_time (void) {
   /* Get current system time for a time stamp of a file. */
   U32 retv, time, v;

   time = fs_get_time ();

   /* Seconds: 0-29 (2-second count) */
   v = (time >> 1) & 0x1F;
   if (v > 29) v = 0;
   retv = v;

   /* Minutes: 0-59 */
   v = (time >> 8) & 0x3F;
   if (v > 59) v = 0;
   retv |= (v << 5);

   /* Hours: 0-23 */
   v = (time >> 16) & 0x1F;
   if (v > 23) v = 23;
   retv |= (v << 11);

   return (retv);
}


/*--------------------------- get_date --------------------------------------*/

static U16 get_date (void) {
   /* Get current system date for a time stamp of a file. */
   U32 retv, date, v;

   date = fs_get_date ();

   /* Days: 1-31 */
   v = date & 0x1F;
   if (v == 0) v = 1;
   retv = v;

   /* Month: 1-12 */
   v = (date >> 8) & 0x0F;
   if (v > 12 || v == 0) v = 1;
   retv |= (v << 5);

   /* Year: 0-127 */
   v  = (date >> 16) - 1980;
   v &= 0x7F;
   retv |= (v << 9);

   return (retv);
}


/*--------------------------- set_time_date ---------------------------------*/

static void set_time_date (FINFO *info, FILEREC *frec) {
   /* Convert date/time info and write to 'info' structure. */
   U32 v;

   v = get_u16 ((U8 *)&frec->WriteTime);
   info->time.hr  = (v >> 11);
   info->time.min = (v >> 5) & 0x3F;
   info->time.sec = (v & 0x1F) << 1;
   v = get_u16 ((U8 *)&frec->WriteDate);
   info->time.day = (v & 0x1F);
   info->time.mon = (v >> 5) & 0x0F;
   info->time.year= ((v >> 9) & 0x7F) + 1980;
}


/*--------------------------- cvt_fatname -----------------------------------*/

static BOOL cvt_fatname (const char *fn, char *en) {
   /* Convert name to short file entry name. */
   /* fn = pointer to the file name
      en = pointer to the entry file name */
   BOOL dot = 0;
   U8   ch0, ch1, ch2;
   U32  i;

   /* Prepare entry name with 'space's. */
   for (i = 0; i < 11; i++) {
      en[i] = ' ';
   }
   /* Terminate entry name. */
   en[i] = 0;

⌨️ 快捷键说明

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