首页 > 代码库 > FATFS 初学之 f_mkfs

FATFS 初学之 f_mkfs

  1 /*-----------------------------------------------------------------------*/  2 /* Create File System on the Drive                                       */  3 /*-----------------------------------------------------------------------*/  4   5 FRESULT f_mkfs (  6     BYTE drv,        /* Logical drive number */  7     BYTE sfd,        /* Partitioning rule 0:FDISK, 1:SFD */  8     UINT au            /* Allocation unit size [bytes] */  9 ) 10 { 11     static const WORD vst[] = { 1024,   512,  256,  128,   64,    32,   16,    8,    4,    2,   0}; 12     static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512}; 13     BYTE fmt, md, sys, *tbl, pdrv, part; 14     DWORD n_clst, vs, n, wsect; 15     UINT i; 16     DWORD b_vol, b_fat, b_dir, b_data;    /* LBA */ 17     DWORD n_vol, n_rsv, n_fat, n_dir;    /* Size */ 18     FATFS *fs; 19     DSTATUS stat; 20  21  22     /* Check mounted drive and clear work area */ 23     if (drv >= _VOLUMES) return FR_INVALID_DRIVE; 24     if (sfd > 1) return FR_INVALID_PARAMETER; 25     if (au & (au - 1)) return FR_INVALID_PARAMETER; 26     fs = FatFs[drv]; 27     if (!fs) return FR_NOT_ENABLED; 28     fs->fs_type = 0; 29     pdrv = LD2PD(drv);    /* Physical drive */ 30     part = LD2PT(drv);    /* Partition (0:auto detect, 1-4:get from partition table)*/ 31  32     /* Get disk statics */ 33     stat = disk_initialize(pdrv); 34     if (stat & STA_NOINIT) return FR_NOT_READY; 35     if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; 36 #if _MAX_SS != 512                    /* Get disk sector size */ 37     if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS) 38         return FR_DISK_ERR; 39 #endif 40     if (_MULTI_PARTITION && part) { 41         /* Get partition information from partition table in the MBR */ 42         if (disk_read(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR; 43         if (LD_WORD(fs->win+BS_55AA) != 0xAA55) return FR_MKFS_ABORTED; 44         tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE]; 45         if (!tbl[4]) return FR_MKFS_ABORTED;    /* No partition? */ 46         b_vol = LD_DWORD(tbl+8);    /* Volume start sector */ 47         n_vol = LD_DWORD(tbl+12);    /* Volume size */ 48     } else { 49         /* Create a partition in this function */ 50         if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128) 51             return FR_DISK_ERR; 52         b_vol = (sfd) ? 0 : 63;        /* Volume start sector */ 53         n_vol -= b_vol;                /* Volume size */ 54     } 55  56     if (!au) {                /* AU auto selection */ 57         vs = n_vol / (2000 / (SS(fs) / 512)); 58         for (i = 0; vs < vst[i]; i++) ; 59         au = cst[i]; 60     } 61     au /= SS(fs);        /* Number of sectors per cluster */ 62     if (au == 0) au = 1; 63     if (au > 128) au = 128; 64  65     /* Pre-compute number of clusters and FAT syb-type */ 66     n_clst = n_vol / au; 67     fmt = FS_FAT12; 68     if (n_clst >= MIN_FAT16) fmt = FS_FAT16; 69     if (n_clst >= MIN_FAT32) fmt = FS_FAT32; 70  71     /* Determine offset and size of FAT structure */ 72     if (fmt == FS_FAT32) { 73         n_fat = ((n_clst * 4) + 8 + SS(fs) - 1) / SS(fs); 74         n_rsv = 32; 75         n_dir = 0; 76     } else { 77         n_fat = (fmt == FS_FAT12) ? (n_clst * 3 + 1) / 2 + 3 : (n_clst * 2) + 4; 78         n_fat = (n_fat + SS(fs) - 1) / SS(fs); 79         n_rsv = 1; 80         n_dir = (DWORD)N_ROOTDIR * SZ_DIR / SS(fs); 81     } 82     b_fat = b_vol + n_rsv;                /* FAT area start sector */ 83     b_dir = b_fat + n_fat * N_FATS;        /* Directory area start sector */ 84     b_data = http://www.mamicode.com/b_dir + n_dir;                /* Data area start sector */ 85     if (n_vol < b_data + au - b_vol) return FR_MKFS_ABORTED;    /* Too small volume */ 86  87     /* Align data start sector to erase block boundary (for flash memory media) */ 88     if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1; 89     n = (b_data + n - 1) & ~(n - 1);    /* Next nearest erase block from current data start */ 90     n = (n - b_data) / N_FATS; 91     if (fmt == FS_FAT32) {        /* FAT32: Move FAT offset */ 92         n_rsv += n; 93         b_fat += n; 94     } else {                    /* FAT12/16: Expand FAT size */ 95         n_fat += n; 96     } 97  98     /* Determine number of clusters and final check of validity of the FAT sub-type */ 99     n_clst = (n_vol - n_rsv - n_fat * N_FATS - n_dir) / au;100     if (   (fmt == FS_FAT16 && n_clst < MIN_FAT16)101         || (fmt == FS_FAT32 && n_clst < MIN_FAT32))102         return FR_MKFS_ABORTED;103 104     switch (fmt) {    /* Determine system ID for partition table */105     case FS_FAT12:    sys = 0x01; break;106     case FS_FAT16:    sys = (n_vol < 0x10000) ? 0x04 : 0x06; break;107     default:         sys = 0x0C;108     }109 110     if (_MULTI_PARTITION && part) {111         /* Update system ID in the partition table */112         tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE];113         tbl[4] = sys;114         if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR;115         md = 0xF8;116     } else {117         if (sfd) {    /* No patition table (SFD) */118             md = 0xF0;119         } else {    /* Create partition table (FDISK) */120             mem_set(fs->win, 0, SS(fs));121             tbl = fs->win+MBR_Table;    /* Create partiton table for single partition in the drive */122             tbl[1] = 1;                        /* Partition start head */123             tbl[2] = 1;                        /* Partition start sector */124             tbl[3] = 0;                        /* Partition start cylinder */125             tbl[4] = sys;                    /* System type */126             tbl[5] = 254;                    /* Partition end head */127             n = (b_vol + n_vol) / 63 / 255;128             tbl[6] = (BYTE)((n >> 2) | 63);    /* Partiiton end sector */129             tbl[7] = (BYTE)n;                /* End cylinder */130             ST_DWORD(tbl+8, 63);            /* Partition start in LBA */131             ST_DWORD(tbl+12, n_vol);        /* Partition size in LBA */132             ST_WORD(fs->win+BS_55AA, 0xAA55);    /* MBR signature */133             if (disk_write(pdrv, fs->win, 0, 1) != RES_OK)    /* Write it to the MBR sector */134                 return FR_DISK_ERR;135             md = 0xF8;136         }137     }138 139     /* Create BPB in the VBR */140     tbl = fs->win;                            /* Clear sector */141     mem_set(tbl, 0, SS(fs));142     mem_cpy(tbl, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code, OEM name */143     i = SS(fs);                                /* Sector size */144     ST_WORD(tbl+BPB_BytsPerSec, i);145     tbl[BPB_SecPerClus] = (BYTE)au;            /* Sectors per cluster */146     ST_WORD(tbl+BPB_RsvdSecCnt, n_rsv);        /* Reserved sectors */147     tbl[BPB_NumFATs] = N_FATS;                /* Number of FATs */148     i = (fmt == FS_FAT32) ? 0 : N_ROOTDIR;    /* Number of rootdir entries */149     ST_WORD(tbl+BPB_RootEntCnt, i);150     if (n_vol < 0x10000) {                    /* Number of total sectors */151         ST_WORD(tbl+BPB_TotSec16, n_vol);152     } else {153         ST_DWORD(tbl+BPB_TotSec32, n_vol);154     }155     tbl[BPB_Media] = md;                    /* Media descriptor */156     ST_WORD(tbl+BPB_SecPerTrk, 63);            /* Number of sectors per track */157     ST_WORD(tbl+BPB_NumHeads, 255);            /* Number of heads */158     ST_DWORD(tbl+BPB_HiddSec, b_vol);        /* Hidden sectors */159     n = get_fattime();                        /* Use current time as VSN */160     if (fmt == FS_FAT32) {161         ST_DWORD(tbl+BS_VolID32, n);        /* VSN */162         ST_DWORD(tbl+BPB_FATSz32, n_fat);    /* Number of sectors per FAT */163         ST_DWORD(tbl+BPB_RootClus, 2);        /* Root directory start cluster (2) */164         ST_WORD(tbl+BPB_FSInfo, 1);            /* FSInfo record offset (VBR+1) */165         ST_WORD(tbl+BPB_BkBootSec, 6);        /* Backup boot record offset (VBR+6) */166         tbl[BS_DrvNum32] = 0x80;            /* Drive number */167         tbl[BS_BootSig32] = 0x29;            /* Extended boot signature */168         mem_cpy(tbl+BS_VolLab32, "NO NAME    " "FAT32   ", 19);    /* Volume label, FAT signature */169     } else {170         ST_DWORD(tbl+BS_VolID, n);            /* VSN */171         ST_WORD(tbl+BPB_FATSz16, n_fat);    /* Number of sectors per FAT */172         tbl[BS_DrvNum] = 0x80;                /* Drive number */173         tbl[BS_BootSig] = 0x29;                /* Extended boot signature */174         mem_cpy(tbl+BS_VolLab, "NO NAME    " "FAT     ", 19);    /* Volume label, FAT signature */175     }176     ST_WORD(tbl+BS_55AA, 0xAA55);            /* Signature (Offset is fixed here regardless of sector size) */177     if (disk_write(pdrv, tbl, b_vol, 1) != RES_OK)    /* Write it to the VBR sector */178         return FR_DISK_ERR;179     if (fmt == FS_FAT32)                            /* Write backup VBR if needed (VBR+6) */180         disk_write(pdrv, tbl, b_vol + 6, 1);181 182     /* Initialize FAT area */183     wsect = b_fat;184     for (i = 0; i < N_FATS; i++) {        /* Initialize each FAT copy */185         mem_set(tbl, 0, SS(fs));            /* 1st sector of the FAT  */186         n = md;                                /* Media descriptor byte */187         if (fmt != FS_FAT32) {188             n |= (fmt == FS_FAT12) ? 0x00FFFF00 : 0xFFFFFF00;189             ST_DWORD(tbl+0, n);                /* Reserve cluster #0-1 (FAT12/16) */190         } else {191             n |= 0xFFFFFF00;192             ST_DWORD(tbl+0, n);                /* Reserve cluster #0-1 (FAT32) */193             ST_DWORD(tbl+4, 0xFFFFFFFF);194             ST_DWORD(tbl+8, 0x0FFFFFFF);    /* Reserve cluster #2 for root dir */195         }196         if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)197             return FR_DISK_ERR;198         mem_set(tbl, 0, SS(fs));            /* Fill following FAT entries with zero */199         for (n = 1; n < n_fat; n++) {        /* This loop may take a time on FAT32 volume due to many single sector writes */200             if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)201                 return FR_DISK_ERR;202         }203     }204 205     /* Initialize root directory */206     i = (fmt == FS_FAT32) ? au : n_dir;207     do {208         if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)209             return FR_DISK_ERR;210     } while (--i);211 212 #if _USE_ERASE    /* Erase data area if needed */213     {214         DWORD eb[2];215 216         eb[0] = wsect; eb[1] = wsect + (n_clst - ((fmt == FS_FAT32) ? 1 : 0)) * au - 1;217         disk_ioctl(pdrv, CTRL_ERASE_SECTOR, eb);218     }219 #endif220 221     /* Create FSInfo if needed */222     if (fmt == FS_FAT32) {223         ST_DWORD(tbl+FSI_LeadSig, 0x41615252);224         ST_DWORD(tbl+FSI_StrucSig, 0x61417272);225         ST_DWORD(tbl+FSI_Free_Count, n_clst - 1);    /* Number of free clusters */226         ST_DWORD(tbl+FSI_Nxt_Free, 2);                /* Last allocated cluster# */227         ST_WORD(tbl+BS_55AA, 0xAA55);228         disk_write(pdrv, tbl, b_vol + 1, 1);    /* Write original (VBR+1) */229         disk_write(pdrv, tbl, b_vol + 7, 1);    /* Write backup (VBR+7) */230     }231 232     return (disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR;233 }
View Code

函数功能:在驱动器上创建一个文件系统(格式化 SD卡)

描述:

f_mkfs函数当_FS_READOLNY == 0并且_USE_MKFS == 1时可用。
f_mkfs函数在驱动器中创建一个FAT文件系统。对于可移动媒介,有两种分区规则:FDISK和SFD,通过参数PartitioningRule选择。FDISK格式在大多数情况下被推荐使用。该函数当前不支持多分区,因此,物理驱动器上已存在的分区将被删除,并且重新创建一个占据全部磁盘空间的新分区。
根据Microsoft发布的FAT规范,FAT分类:FAT12/FAT16/FAT32,由驱动器上的簇数决定。因此,选择哪种FAT分类,取决于卷大小和指定的簇大小。簇大小影响文件系统的性能,并且大簇会提高性能。

 

例:

 1   FATFS fs; 2   FIL file; 3   FRESULT res; 4   char array[512]={0}, *parray = array; 5    6   res = f_mount(0, &fs); 7   res = f_mkfs(0 , 0, _MAX_SS); 8   res = f_open(&file, "data.txt", FA_OPEN_ALWAYS | FA_WRITE | FA_READ); 9   f_printf(&file, "%s\n", "Success");        /* "Success" */10   parray = f_gets(parray , 8, &file);11   LCMTextOutExt(  0, 0, parray );12   f_close(&file);13   f_mount(0, NULL);
View Code