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

📄 fs_fdefrag.c

📁 keil arm flash fs 最新版 在Keil arm下使用
💻 C
字号:
/*----------------------------------------------------------------------------
 *      R T L  -  F l a s h   F i l e   S y s t e m
 *----------------------------------------------------------------------------
 *      Name:    FS_FDEFRAG.C 
 *      Purpose: File System Defragment Function
 *      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"

static BOOL alloc_free_bl (FDBUF *fb, IOB *fcb);
static BOOL get_next_file (IOB *fcb);
static BOOL copy_file (FDBUF *fb, IOB *fcb);
static U32  read_cbuf (IOB *fcb);
static BOOL write_cbuf (FDBUF *fb, IOB *fcb, U32 len);
static BOOL get_fblock (IOB *fcb);
static void delete_file (IOB *fcb, BOOL del_temp);

#define CBUFLEN  256
static U32 cbuf[CBUFLEN/4+1];
static FALLOC alloc;

/*--------------------------- fdefrag ---------------------------------------*/

int fdefrag (const char *drive) {
   /* Re-sort FlashFS files so that used Flash pages are reduced. */
   IOB *fcb,*iop;
   int handle;
   FDBUF fwr;
   BOOL defrag_fail;
   U32 i,adr,bl,bflag;

   /* Find an unused _iob structure. */
   if ((handle = fs_find_iob ()) == EOF) {
      return (1);
   }
   fcb = &_iob[handle];
   /* Get the drive index. */
   fcb->drive = fs_get_drive (drive);
   if (fcb->drive == DRV_NONE && *drive == 0) {
      /* Empty string provided for a drive name. */
      fcb->drive = _DEF_DRIVE;
   }
   if (fcb->drive == DRV_MCARD) {
      /* Memory Card currently not supported. */
      return (1);
   }
   /* Set drive parameters. */
   if (fs_set_params (fcb) == __FALSE) {
      return (1);
   }

   /* Check if there is an opened file. */
   for (i = 0, iop = &_iob[0]; i < _NFILE; iop++, i++) {
      if (iop->drive != fcb->drive) {
         continue;
      }
      if ((iop->flags & (_IOWRT | _IOREAD))) {
         /* Error, a file is opened. */
         return (1);
      }
   }

   /* Erase all invalidated Flash Blocks if any. */
   for (bl = 0; bl < fcb->NumSect; bl++) {
      adr = fs_adr_sig (bl, fcb);
      fs_rd_sig (adr, &bflag);
      if (bflag != fcb->InitVal) {
         /* Check if this Flash Block is all invalidated */
         if (fs_BlockInvalid (bl, fcb) == __TRUE) {
            fs_InitBlock (bl, fcb);
         }
      }
   }

   /* Scan all files stored to FlashFS. */
   fcb->fileID = 0;
   fwr.ftop    = 0;
   fwr.fbot    = 0;
   defrag_fail  = __FALSE;
   while (get_next_file (fcb) == __TRUE) {
      if (copy_file (&fwr, fcb) == __FALSE) {
         /* Defragmentation failed, delete last temp file. */
         delete_file (fcb, __TRUE);
         defrag_fail = __TRUE;
         break;
      }
      delete_file (fcb, __FALSE);
   }

   /* Update FBlock usage signatures, and erase old pages. */
   for (bl = 0; bl < fcb->NumSect; bl++) {
      adr = fs_adr_sig (bl, fcb);
      fs_rd_sig (adr, &bflag);
      if (bflag == fcb->InitVal) {
         continue;
      }
      if ((bflag ^ BlockTEMP) == fcb->InitVal) {
         bflag = fcb->InitVal ^ BlockUSED;
         if (fs_get_freeMem (bl, fcb) == 0) {
            bflag = fcb->InitVal ^ BlockFULL;
         }
         fs_WriteBlock ((adr & ~1), &bflag, 4, fcb);
         continue;
      }
      if (defrag_fail == __FALSE) {
         fs_InitBlock (bl, fcb);
      }
   }
   if (defrag_fail == __TRUE) {
      return (2);
   }
   return (0);
}


/*--------------------------- alloc_free_bl ---------------------------------*/

static BOOL alloc_free_bl (FDBUF *fb, IOB *fcb) {
   U32 bl,adr,bflag;

   /* Allocate an empty Flash Block. */
   for (bl = 0; bl < fcb->NumSect; bl++) {
      adr = fs_adr_sig (bl, fcb);
      fs_rd_sig (adr, &bflag);
      if (bflag == fcb->InitVal) {
         bflag = fcb->InitVal ^ BlockTEMP;
         fs_WriteBlock ((adr & ~1), &bflag, 4, fcb);
         fb->fblock = bl;
         fb->fbot   = 0;
         fb->ftop   = ((DEVCONF *)fcb->DevCfg)[bl].bEnd   -
                      ((DEVCONF *)fcb->DevCfg)[bl].bStart -  sizeof(FALLOC);
         return (__TRUE);
      }
   }
   return (__FALSE);
}


/*--------------------------- get_next_file ---------------------------------*/

static BOOL get_next_file (IOB *fcb) {
   FALLOC fa;
   U32 bl,adr,prev;
   U32 fid,nid;

   /* Search for file with next higher fileID. */
   fid = fcb->fileID | 0x8000;
   nid = 0xFFFF;
   for (bl = 0; bl < fcb->NumSect; bl++) {
      adr = fs_adr_sig (bl, fcb);
      adr = fs_rd_sig (adr, &fa.end);
      if (fa.end == fcb->InitVal || fa.end == (fcb->InitVal ^ BlockTEMP)) {
         /* Skip free or temp Flash Blocks. */
         continue;
      }
      for (prev = 0; ; prev = fa.end) {
         adr = fs_rd_alloc (adr, &fa);
         if (fa.fileID > fid && fa.fileID < nid) {
            nid = fa.fileID;
            /* File name block is word aligned. */
            fcb->_fblock = bl;
            fcb->_fbot   = (prev + 3) & ~3;
            fcb->_ftop   = fa.end;
            if (nid == fid+1) {
               goto x;
            }
         }
         if (fa.end == fcb->InitVal) break;
      }
   }
   if (nid == 0xFFFF) {
      /* Next file not found. */
      return (__FALSE);
   }
x: fcb->fileID = nid & 0x7FFF;
   fcb->_fidx  = 0;
   return (__TRUE);
}


/*--------------------------- copy_file -------------------------------------*/

static BOOL copy_file (FDBUF *fb, IOB *fcb) {
   U32 n,nr;

   /* Make sure that 'filename' starts on 4-byte boundary */
   fb->fbot = (fb->fbot + 3) & ~3;
   if (fb->ftop < fb->fbot + 256) {
      /* Allocate an empty Flash Block. */
      if (alloc_free_bl (fb, fcb) == __FALSE) {
         /* Error, no empty Flash Blocks left */
         return (__FALSE);
      }
   }
   /* Copy File Name first. */
   n = (fcb->_ftop - fcb->_fbot + 3) & ~3;
   if (n > CBUFLEN) {
      n = CBUFLEN;
   }
   fs_ReadBlock  (((DEVCONF *)fcb->DevCfg)[fcb->_fblock].bStart + fcb->_fbot,
                  &cbuf, n, fcb);
   fs_WriteBlock (((DEVCONF *)fcb->DevCfg)[fb->fblock].bStart + fb->fbot, 
                  &cbuf, n, fcb);

   fb->fbot += n;

   alloc.end    = fb->fbot;
   alloc.fileID = fcb->fileID | 0x8000;
   alloc.index  = 0;
   fs_WriteBlock (((DEVCONF *)fcb->DevCfg)[fb->fblock].bStart + fb->ftop,
                  &alloc, sizeof (FALLOC), fcb);
   fb->ftop  -= sizeof (FALLOC);

   /* Copy the file content. */
   fcb->_ftop = 0;
   fcb->_fbot = 0;
   fcb->_fidx = 0;
   fb->index  = 0;

   while ((nr = read_cbuf (fcb)) != 0) {
      if (write_cbuf (fb, fcb, nr) == __FALSE) {
         return (__FALSE);
      }
      if (nr < CBUFLEN) {
         break;
      }
   }

   /* Close this file, write File Allocation Information. */
   alloc.end    = fb->fbot;
   alloc.fileID = fcb->fileID;
   alloc.index  = fb->index;
   fs_WriteBlock (((DEVCONF *)fcb->DevCfg)[fb->fblock].bStart + fb->ftop, 
                  &alloc, sizeof (FALLOC), fcb);
   fb->ftop -= sizeof (FALLOC);
   return (__TRUE);
}


/*--------------------------- read_cbuf --------------------------------------*/

static U32 read_cbuf (IOB *fcb) {
   U32 len,n;

   len = 0;
   /* Read fragmented file to buffer. */
   while (1) {
      if (fcb->_ftop == fcb->_fbot) {
         if (get_fblock (fcb) == __FALSE) {
            break;
         }
      }
      n = fcb->_ftop - fcb->_fbot;
      if (n > CBUFLEN - len) {
         n = CBUFLEN - len;
      }
      fs_ReadBlock (((DEVCONF *)fcb->DevCfg)[fcb->_fblock].bStart + fcb->_fbot,
                    (U8 *)&cbuf + len, n, fcb);
      fcb->_fbot += n;
      len        += n;
      if (len >= CBUFLEN) {
         break;
      }
   }
   return (len);
}


/*--------------------------- write_cbuf -------------------------------------*/

static BOOL write_cbuf (FDBUF *fb, IOB *fcb, U32 len) {
   U32 size,n;
   S8 *pb;

   pb = (S8 *)&cbuf;
   while (len) {
      n = len;
      size = fb->ftop - fb->fbot - sizeof (FALLOC);
      if (n > size) {
         n = size;
      }
      len -= n;
      fs_WriteBlock (((DEVCONF *)fcb->DevCfg)[fb->fblock].bStart + fb->fbot, 
                     pb, n, fcb);
      fb->fbot += n;
      pb       += n;

      if ((fb->ftop - sizeof (FALLOC)) > fb->fbot) {
         /* Enough space in current Flash Block */
         continue;
      }

      /* No more free space, write File Allocation Information */
      alloc.end    = fb->fbot;
      alloc.fileID = fcb->fileID;
      alloc.index  = fb->index;
      fs_WriteBlock (((DEVCONF *)fcb->DevCfg)[fb->fblock].bStart + fb->ftop,
                     &alloc, sizeof (FALLOC), fcb);
      fb->ftop -= sizeof (FALLOC);
      fb->index++;

      /* Current Flash Block is full, allocate next one */
      if (alloc_free_bl (fb, fcb) == __FALSE) {
         /* Error, no empty Flash Blocks left */
         return (__FALSE);
      }
   }
   return (__TRUE);
}


/*--------------------------- get_fblock -------------------------------------*/

static BOOL get_fblock (IOB *fcb) {
   FALLOC fa;
   U32 i,bl,adr,prev;

   bl = fcb->_fblock;
   for (i = 0; i < fcb->NumSect; i++) {
      /* Search for file blocks identified with identification 'fileID' */
      adr = fs_adr_sig (bl, fcb);
      adr = fs_rd_sig (adr, &fa.end);
      if (fa.end == fcb->InitVal || fa.end == (fcb->InitVal ^ BlockTEMP)) {
         /* Skip free or temp Flash Blocks. */
         goto next;
      }
      for (prev = 0; ; prev = fa.end) {
         adr = fs_rd_alloc (adr, &fa);
         if (fa.fileID == fcb->fileID  &&  fa.index == fcb->_fidx) {
            /* Set Current File Block parameters */
            fcb->_fblock = bl;
            /* All file blocks are 4-byte aligned. */
            fcb->_fbot   = (prev + 3) & ~3;
            fcb->_ftop   = fa.end;
            fcb->_fidx++; 
            return (__TRUE);
         }
         if (fa.end == fcb->InitVal) break;
      }
next: if (++bl == fcb->NumSect) {
         bl = 0;
      }
   } 
   return (__FALSE);
}

/*--------------------------- delete_file -----------------------------------*/

static void delete_file (IOB *fcb, BOOL del_temp) {
   /* Low level file delete function. */
   FALLOC fa;
   U32 bl,adr,invalid;

   for (bl = 0; bl < fcb->NumSect; bl++) {
      /* Search for file blocks identified with identification 'fileID' */
      adr = fs_adr_sig (bl, fcb);
      adr = fs_rd_sig (adr, &fa.end);
      if (del_temp == __FALSE) {
         if (fa.end == fcb->InitVal || fa.end == (fcb->InitVal ^ BlockTEMP)) {
            /* Skip free or temp Flash Blocks. */
            continue;
         }
      }
      else {
         if (fa.end != (fcb->InitVal ^ BlockTEMP)) {
            /* Delete a file in temp Flash Block. */
            continue;
         }
      }
      do {
         adr = fs_rd_alloc (adr, &fa);
         if ((fa.fileID & 0x7FFF) == fcb->fileID) {
            /* Clear the fileID values */
            invalid = ~fcb->InitVal;
            fs_WriteBlock ((adr & ~1) + 12, &invalid, 4, fcb);
         }
      } while (fa.end != fcb->InitVal);

      /* Check if this Flash Block is all invalidated */
      if (fs_BlockInvalid (bl, fcb) == __TRUE) {
         /* All file blocks stored in this Flash Block are invalid */
         fs_InitBlock (bl, fcb);
      }
   }
}

/*----------------------------------------------------------------------------
 * end of file
 *---------------------------------------------------------------------------*/

⌨️ 快捷键说明

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