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

📄 fs_fat.c

📁 keil arm flash fs 最新版 在Keil arm下使用
💻 C
📖 第 1 页 / 共 5 页
字号:
   /* Write also cached Data and FAT table. */
   write_cache (0);
   cache_fat (0);
   return (__TRUE);
}


/*--------------------------- fat_set_fpos ----------------------------------*/

BOOL fat_set_fpos (IOB *fcb, U32 pos) {
   /* Set File Position pointer. */
   U32 i;

   if (pos > fcb->fsize) {
      pos = fcb->fsize;
   }
   fcb->_currDatSect = (pos / 512) % mmc.SecPerClus;
   fcb->_currDatClus = fcb->_firstClus;
   for (i = pos / mmc.ClusSize; i; i--) {
      /* Scan the cluster chain. */
      set_next_clus (&fcb->_currDatClus);
   }
   fcb->fpos = pos;

   return (__TRUE);
}


/*--------------------------- fat_rename ------------------------------------*/

BOOL fat_rename (const char *old, const char *new, IOB *fcb) {
   /* Rename a file or directory to new name. */
   U8 type;

   if (mmc.FatType == FS_RAW) {
      /* RAW File System or FAT not initialized. */
      return (__FALSE);
   }

   /* Remove starting '\' if it exists. */
   if (*old == '\\') old++;

   /* Remove starting '\' if it exists. */
   if (*new == '\\') new++;

   /* Exit function if "old" on "new" is not given. */
   if (*old == 0 || *new == 0) {
      return(__FALSE);
   }

   /* Search for directory. */
   fcb->_firstClus = 0;
   if (fat_find_dir (old, fcb, 0) == __FALSE) {
      /* Directory does not exist. */
      return (__FALSE);
   }

   type = ENT_DIR;
   if (name_buf[0]) {
      if (check_name (new, fcb, ENT_FILE) == __TRUE) {
         /* New file already exist. */
         return (__FALSE);
      }

      type = ENT_FILE;
      /* Search for file if file name exists. */
      if (find_name (name_buf, fcb, ENT_FILE) == __FALSE) {
         /* File does not exist. */
         return (__FALSE);
      }
   }
   else {
      if (check_name (new, fcb, ENT_DIR) == __TRUE) {
         /* New directory already exist. */
         return (__FALSE);
      }
   }
   
   if (rename_entries (new, fcb, type) == __FALSE) {
      /* If rename was unsuccessfully. */
      return (__FALSE);
   }

   /* File or directory renamed. */
   return (__TRUE);
}


/*--------------------------- write_label -----------------------------------*/

static BOOL write_label (const char *label) {
   /* Write a drive label to Root Directory. */
   FILEREC *frec;
   U32 i;
   U8 ch;

   read_sector (mmc.BootRecSec + mmc.RootDirAddr);
   frec = (FILEREC *)&ca.buf[0];
   memset (frec, 0, 32);
   for (i = 0; i < 11; i++) {
      ch = val_char_lab (label[i]);
      if (ch == 0) break;
      frec->FileName[i] = ch;
   }
   for (  ; i < 11; i++) {
      frec->FileName[i] = ' ';
   }
   frec->Attr      = ATTR_VOLUME_ID;
   set_u16 ((U8 *)&frec->WriteDate, get_date ());
   set_u16 ((U8 *)&frec->WriteTime, get_time ());
   write_sector (mmc.BootRecSec + mmc.RootDirAddr);
   return (__TRUE);
}


/*--------------------------- set_next_clus ---------------------------------*/

static BOOL set_next_clus (U32 *ptr_clus) {
   /* Read next Cluster address from FAT table. */
   U32 sect,ofs,next;
   U32 clus = *ptr_clus;

   /* Read a part of FAT table to buffer. */
   sect = get_fat_sect (clus);
   cache_fat (sect);
   next = 0;
   switch (mmc.FatType) {
      case FS_FAT12:
         ofs  = ((clus * 3) / 2) & 0x1FF;
         if (ofs < 511) {
            next = get_u16 (&fat.buf[ofs]);
         }
         else {
            /* This cluster spans on two sectors in the FAT. */
            next = fat.buf[511];
            cache_fat (sect+1);
            next |= fat.buf[0] << 8;
         }
         if (clus & 0x001) {
            next >>= 4;
         }
         else {
            next &= 0xFFF;
         }
         break;

      case FS_FAT16:
         ofs  = (clus & 0xFF) << 1;
         next = *(U16 *)&fat.buf[ofs];
         break;

      case FS_FAT32:
         ofs  = (clus & 0x7F) << 2;
         next = *(U32 *)&fat.buf[ofs];
         break;

      default:
         return (__FALSE);
   }
   *ptr_clus = next;
   return (__TRUE);
}


/*--------------------------- get_free_clus ---------------------------------*/

static BOOL get_free_clus (U32 *ptr_clus) {
   /* Scan FAT Table and find first free cluster. */
   U32 sect,ofs,next;
   U32 clus = *ptr_clus;

   for (clus = top_clus; clus < (mmc.DataClusCnt + 2); clus++) {
      /* Read a part of FAT table to buffer. */
      sect = get_fat_sect (clus);
      cache_fat (sect);
      switch (mmc.FatType) {
         case FS_FAT12:
            ofs  = ((clus * 3) / 2) & 0x1FF;
            if (ofs < 511) {
               next = get_u16 (&fat.buf[ofs]);
            }
            else {
               /* This cluster spans on two sectors in the FAT. */
               next = fat.buf[511];
               cache_fat (sect+1);
               next |= fat.buf[0] << 8;
            }
            if (clus & 0x001) {
               next >>= 4;
            }
            else {
               next &= 0xFFF;
            }
            break;

         case FS_FAT16:
            ofs  = (clus & 0xFF) << 1;
            next = get_u16 (&fat.buf[ofs]);
            break;

         case FS_FAT32:
            ofs  = (clus & 0x7F) << 2;
            next = get_u32 (&fat.buf[ofs]);
            break;

         default:
            return (__FALSE);
      }
      if (next == 0) {
         if (clus_in_use (clus) == __FALSE) {
            *ptr_clus = clus;
            top_clus  = clus + 1;
            return (__TRUE);
         }
      }
   }
   /* Disk Full, no free clusters found. */
   top_clus = clus;
   return (__FALSE);
}


/*--------------------------- clus_in_use -----------------------------------*/

static BOOL clus_in_use (U32 clus) {
   /* Check if cluster in use by another file. */
   IOB *fcb;
   U32 i,nfile = _NFILE;

   for (i = 0, fcb = &_iob[0]; i < nfile; fcb++, i++) {
      if (!(fcb->flags & _IOWRT)) {
         /* File not opened for writing. */
         continue;
      }
      if (fcb->_currDatClus == clus) {
         /* This cluster used by another file. */
         return (__TRUE);
      }
   }
   return (__FALSE);
}


/*--------------------------- clear_clus ------------------------------------*/

static BOOL clear_clus (U32 clus) {
   /* Clear current cluster. */
   U32 i;
   U32 sect = clus_to_sect(clus);

   /* Use cache for faster write. */
   memset(ca.buf, 0, 512);
   for (i = 0; i < mmc.SecPerClus; i++) {
      write_cache(sect + i);
   }
   /* Flush the cache buffer when done. */
   write_cache (0);
   return (__TRUE);
}


/*--------------------------- write_fat_link --------------------------------*/

static BOOL write_fat_link (U32 clus, U32 next_clus) {
   /* Write FAT table, update link cluster at cluster address. */
   U32 sect,ofs,temp;

   sect = get_fat_sect (clus);
   cache_fat (sect);

   switch (mmc.FatType) {
      case FS_FAT12:
         next_clus &= 0x0FFF;
         ofs  = ((clus * 3) / 2) & 0x1FF;
         if (ofs < 511) {
            temp = get_u16 (&fat.buf[ofs]);
            if (clus & 0x001) {
               temp = (temp & 0x000F) | (next_clus << 4);
            }
            else {
               temp = (temp & 0xF000) | next_clus;
            }
            set_u16 (&fat.buf[ofs], temp);
         }
         else {
            /* This cluster spans on two sectors in the FAT. */
            if (clus & 0x001) {
               fat.buf[511] = (fat.buf[511] & 0x0F) | (next_clus << 4);
            }
            else {
               fat.buf[511] = (U8)next_clus;
            }
            fat.dirty = __TRUE;
            cache_fat (++sect);
            if (clus & 0x001) {
               fat.buf[0] = next_clus >> 4;
            }
            else {
               fat.buf[0] = (fat.buf[0] & 0xF0) | (next_clus >> 8);
            }
         }
         break;

      case FS_FAT16:
         ofs  = (clus & 0xFF) << 1;
         set_u16 (&fat.buf[ofs], next_clus);
         break;

      case FS_FAT32:
         ofs  = (clus & 0x7F) << 2;
         set_u32 (&fat.buf[ofs], next_clus);
         break;

      default:
         return (__FALSE);
   }
   if (free_clus) free_clus--;
   fat.dirty = __TRUE;
   return (__TRUE);
}


/*--------------------------- unlink_clus_chain -----------------------------*/

static BOOL unlink_clus_chain (U32 clus) {
   /* Remove a cluster chain starting with 'clus'. Reset the values to 0.*/
   U32 sect,ofs,next,temp;

   if (clus < 2) {
      /* An empty file, do nothing here. */
      return (__TRUE);
   }

   while (clus < (mmc.DataClusCnt + 2)) {
      /* Reset top used cluster index. */
      if (clus < top_clus) {
         top_clus = clus;
      }
      sect = get_fat_sect (clus);
      cache_fat (sect);

      switch (mmc.FatType) {
         case FS_FAT12:
            ofs  = ((clus * 3) / 2) & 0x1FF;
            if (ofs < 511) {
               next = get_u16 (&fat.buf[ofs]);
               if (clus & 0x001) {
                  temp = next & 0x000F;
                  next >>= 4;
               }
               else {
                  temp = next & 0xF000;
                  next &= 0xFFF;
               }
               set_u16 (&fat.buf[ofs], temp);
            }
            else {
               /* This cluster spans on two sectors in the FAT. */
               next = fat.buf[511];
               if (clus & 0x001) {
                  fat.buf[511] &= 0x0F;
               }
               else {
                  fat.buf[511] = 0;
               }
               fat.dirty = __TRUE;
               cache_fat (++sect);
               next |= fat.buf[0] << 8;
               if (clus & 0x001) {
                  fat.buf[0] = 0;
                  next >>= 4;
               }
               else {
                  fat.buf[0] &= 0xF0;
                  next &= 0xFFF;
               }
            }
            goto chk_eoc;

         case FS_FAT16:
            ofs  = (clus & 0xFF) << 1;
            next = get_u16 (&fat.buf[ofs]);
            *(U16 *)&fat.buf[ofs] = 0;
            goto chk_eoc;

         case FS_FAT32:
            ofs  = (clus & 0x7F) << 2;
            next = get_u32 (&fat.buf[ofs]);
            *(U32 *)&fat.buf[ofs] = 0;
chk_eoc:    fat.dirty = __TRUE;
            if (is_EOC (next) == __TRUE) {
               cache_fat (0);
               return (__TRUE);
            }
            break;

         default:
            return (__FALSE);
      }
      clus = next;
      free_clus++;
   }
   cache_fat (0);
   /* Failed, something wrong with FAT table. */
   return (__FALSE);
}


/*--------------------------- alloc_new_clus --------------------------------*/

static BOOL alloc_new_clus (U32 *ptr_clus, U8 wr_fat_link) {
   /* Allocate a new cluster. */
   U32 clus = *ptr_clus;

   if (get_free_clus (ptr_clus) == __FALSE) {
      /* Failed to allocate a free cluster. */
      return (__FALSE);
   }

   write_fat_link (*ptr_clus, get_EOC());
   if (wr_fat_link) {
      /* Update also a FAT cluster chain. */
      write_fat_link (clus, *ptr_clus);
   }
   cache_fat (0);
   
   /* New cluster allocated successfully. */
   return (__TRUE);
}


/*--------------------------- count_free_clus -------------------------------*/

static U32 count_free_clus (void) {
   /* Scan FAT table and Count number of free clusters. */
   U32 clus,sect,ofs,next,nfree;

   nfree = 0;
   if (mmc.FatType == FS_FAT12) {
      for (clus = 2; clus < (mmc.DataClusCnt + 2); clus++) {
         /* Read a part of FAT table to buffer. */
         sect = get_fat_sect (clus);
         cache_fat (sect);
         ofs  = ((clus * 3) / 2) & 0x1FF;
         if (ofs < 511) {
            next = get_u16 (&fat.buf[ofs]);
         }
         else {
            /* This cluster spans on two sectors in the FAT. */
            next = fat.buf[511];
            cache_fat (sect+1);
            next |= fat.buf[0] << 8;
         }
         if (clus & 0x001) {
            next >>= 4;
         }
         else {
            next &= 0xFFF;
         }
         if (next == 0) {
            nfree++;
         }
      }
      return (nfree);
   }
   if (mmc.FatType == FS_FAT16) {

⌨️ 快捷键说明

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