FATFS 初学之 f_mkfs
2014-08-14 10:40 Danhuise 阅读(7892) 评论(0) 编辑 收藏 举报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 = 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 #endif 220 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 }
函数功能:在驱动器上创建一个文件系统(格式化 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);