原创 深入理解文件系统(一)

2010-3-28 13:07 4795 8 9 分类: MCU/ 嵌入式

 


       上一个名字用的时间太长了,换个名字吧。


一、通过格式化命令-看磁盘文件系统的建立过程<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


 


1、添加format命令,单步调试


       所有的底层驱动函数都已经准备好。添加格式化命令format后,编译下载。


       Format命令的执行主要是调用f_mkfs()函数,下面进行单步调试


以下主要列出函数的主要执行步骤


res=f_mkfs( 0, 1, 4096 ); //1表示不需要引导扇区。40968个扇区。


进入f_mkfs()函数,这里只列出主要执行步骤:


       if (disk_ioctl(drv, GET_SECTOR_COUNT, &n_part) != RES_OK || n_part < MIN_SECTOR)


              return FR_MKFS_ABORTED;这个函数调用后,n_part=0x<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />000F,3400 = 996 352,这是SD的总块数。


 


       allocsize /= SS(fs);            等于8/* Number of sectors per cluster */


       n_clst = n_part / allocsize;  //等于0x1E680 = 124 544 簇。


       if (n_clst >= 0xFFF5) fmt = FS_FAT32; 所以文件系统确定为FAT32类型。


       n_fat = ((n_clst * 4) + 8 + SS(fs) - 1) / SS(fs);  等于0x3CE = 974,表示FAT要占据974个扇区。


       n_rsv = 33 - partition;  保留扇区32个。


       n_dir = 0;


 


       b_fat = b_part + n_rsv;                  /* FATs start sector  32扇区*/


       b_dir = b_fat + n_fat * N_FATS;   /* Directory start sector  0x3EE =1006,由于FAT表个数设为1个,所以目录区=FAT起始+FAT占用扇区数*/


       b_data = b_dir + n_dir;                  /* Data start sector */


以上三项确定 FAT区域、根目录区、数据区的起始扇区。


 


disk_ioctl(drv, GET_BLOCK_SIZE, &n) != RES_OK这个函数调用没有正确返回 可擦出扇区的总数。接下来程序会出错,因此退出,修改disk_ioctl()函数后,再次分析。把这个函数返回值直接改为32。并且把FAT表的个数定义为2.


N_FATS改为2后,根目录区、数据区的起始扇区的起始扇区变为0x7BC=1980扇区。继续往下执行。


       n = (b_data + n - 1) & ~(n - 1);


       n_fat += (n - b_data) / N_FATS;这两句话对fat所占扇区数进行了修正,保证擦除时,以32个扇区为一个单位。


n_clst = (n_part - n_rsv - n_fat * N_FATS - n_dir) / allocsize;  =0x1E588


 


       tbl = fs->win;                                                       /* Clear buffer */


       mem_set(tbl, 0, SS(fs));   清零文件系统缓冲区。


 


       mem_set(tbl, 0, SS(fs));


       ST_DWORD(tbl+BS_jmpBoot, 0x90FEEB);                 /* Boot code (jmp $, nop) */


       ST_WORD(tbl+BPB_BytsPerSec, SS(fs));             /* Sector size */


       tbl[BPB_SecPerClus] = (BYTE)allocsize;         /* Sectors per cluster */


       ST_WORD(tbl+BPB_RsvdSecCnt, n_rsv);                    /* Reserved sectors */


上面的工作主要是填充 引导扇区缓冲区,也就是常说的DBR扇区缓冲,等所有的参数写好,就可以写回磁盘。


       ST_WORD(tbl+BS_55AA, 0xAA55);                      /* Signature */


       if (disk_write(drv, tbl, b_part+0, 1) != RES_OK)


              return FR_DISK_ERR;  //这就是在写有效引导标志 sec[510]=0x55, sec[511]=0xAA


       if (fmt == FS_FAT32)


              disk_write(drv, tbl, b_part+6, 1); //FAT32在第六扇区有个备份引导扇区。


       for (m = 0; m < N_FATS; m++) {


              mem_set(tbl, 0, SS(fs));          /* 1st sector of the FAT  */


              if (fmt != FS_FAT32) {


                     n = (fmt == FS_FAT12) ? 0x00FFFF00 : 0xFFFFFF00;


                     n |= partition;


                     ST_DWORD(tbl, n); /* Reserve cluster #0-1 (FAT12/16) */


              } else {


                     ST_DWORD(tbl+0, 0xFFFFFFF8);     /* Reserve cluster #0-1 (FAT32) */


                     ST_DWORD(tbl+4, 0xFFFFFFFF);


                     ST_DWORD(tbl+8, 0x0FFFFFFF);     /* Reserve cluster #2 for root dir */     }    //0和簇1保留,簇2分配给根目录区。


              if (disk_write(drv, tbl, b_fat++, 1) != RES_OK)


                     return FR_DISK_ERR;


 


              mem_set(tbl, 0, SS(fs));          /* Following FAT entries are filled by zero */  //接下来所有的扇区都清0,表示该簇未被占用。


              for (n = 1; n < n_fat; n++) {


                     if (disk_write(drv, tbl, b_fat++, 1) != RES_OK)


                            return FR_DISK_ERR;


              }    //第一次是写从0x21扇区开始,总共 0x3CF个扇区(第一个扇区已经写了)。第二次开始时是备份引导扇区,0x20+0x3D0=0x3F0。同理,第一扇区与0x21扇区相同,后面都清零。


 


Format命令要执行较长的时间,主要就是FAT表接近2000个扇区要清零。


 


 


       m = (BYTE)((fmt == FS_FAT32) ? allocsize : n_dir);  m=8,每簇8扇区。


       do {


              if (disk_write(drv, tbl, b_fat++, 1) != RES_OK)


                     return FR_DISK_ERR;


       } while (--m);  //以上部分是将根目录区的8个扇区清零,表示目录项未被占用。


 


       if (fmt == FS_FAT32) {


              ST_WORD(tbl+BS_55AA, 0xAA55);


              ST_DWORD(tbl+FSI_LeadSig, 0x41615252);


              ST_DWORD(tbl+FSI_StrucSig, 0x61417272);


              ST_DWORD(tbl+FSI_Free_Count, n_clst - 1); //根目录区已经用掉了一簇。


              ST_DWORD(tbl+FSI_Nxt_Free, 0xFFFFFFFF);


              disk_write(drv, tbl, b_part+1, 1);  //分别写入1号和7号扇区。


              disk_write(drv, tbl, b_part+7, 1);


       }  //这是写FAT32文件系统的FSI扇区,包括空闲簇总数和上次分配的簇号。


 


FAT32文件系统的格式化到此完成。


 


2、再以Fdisk的方式格式化一次,这时候格式系统要写 MBR扇区FAT引导扇区不在 0号扇区了。同时MBR要建立分区表,以找到DBR引导扇区。其过程与上述差不多,只是多执行了以下代码,详细过程就不叙述了。


       if (!partition) {


              DWORD n_disk = b_part + n_part;


              mem_set(fs->win, 0, SS(fs));


              tbl = fs->win+MBR_Table;  //分区表从0x1BE开始。


              ST_DWORD(tbl, 0x00010180);           /* Partition start in CHS */ Table[0x1BE] = 0x80,表明该分区是活动扇区00表示开始柱面0101表示开始扇区、开始磁头


              if (n_disk < 63UL * 255 * 1024) {  /* Partition end in CHS */


                     n_disk = n_disk / 63 / 255;


                     tbl[7] = (BYTE)n_disk;   //表示结束的柱面。


                     tbl[6] = (BYTE)((n_disk >> 2) | 63); //结束的扇区。


              } else {


                     ST_WORD(&tbl[6], 0xFFFF); //


              }


              tbl[5] = 254;  //结束的磁头。


              if (fmt != FS_FAT32)               /* System ID */


                     tbl[4] = (n_part < 0x10000) ? 0x04 : 0x06;


              else


                     tbl[4] = 0x0c;  // 表示该分区类型为win95 FAT32


              ST_DWORD(tbl+8, 63);               /*起始扇区 0x3F in LBA */


              ST_DWORD(tbl+12, n_part);              /*分区的大小,总扇区数减去MBR及其占据的一个柱面。 */


              ST_WORD(tbl+64, 0xAA55);              /* Signature */


              if (disk_write(drv, fs->win, 0, 1) != RES_OK)


                     return FR_DISK_ERR;


              partition = 0xF8;  //MBR标志。


       } else {


              partition = 0xF0;


       }


3、观察在有MBR区域的情况下,如何检查文件系统


       fmt = check_fs(fs, bsect = 0);        /* 检查0扇区的时候,没有发现FAT文件系统扇区,但是有0x55 0xAA标志,说明这是有效磁盘,但是返回1. */


       if (fmt == 1) {             /* 表明可能存在分区 */


              /* Check a partition listed in top of the partition table */


              tbl = &fs->win[MBR_Table + LD2PT(vol) * 16];    /* Partition table */


              if (tbl[4]) {           实际这里应该是0x0c,表示FAT32系统


                     bsect = LD_DWORD(&tbl[8]);                                /* 这个是文件系统 引导扇区的号码 */


                     fmt = check_fs(fs, bsect);                                   /* 再到这个扇区检查是否存在 FAT文件系统标志 */      }      }


 


执行过后,仍然能够建立完整的 文件系统信息 结构体,只是里面的 FAT分配起始扇区、数据区起始扇区地址相对 没有MBR的时候改变了,其它都差不多。


 


 


 


 

PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

tengjingshu_112148725 2010-3-30 00:08

文章是在太好了!
相关推荐阅读
nthq2004 2010-05-08 20:04
USB自定义设备驱动02
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />  本来还想编写应用程序测试一下自定...
nthq2004 2010-05-07 21:35
USB自定义设备驱动01
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />  一、USB设备驱动入门1、学习目...
nthq2004 2010-05-04 21:01
智林开发板上实现自定义的USB HID设备
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />  一、自定义HID设备的相关概念1...
nthq2004 2010-05-01 21:58
U盘例程在智林开发板上的移植
 <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> 一、移植前的准备工作1、有哪些操...
nthq2004 2010-04-30 19:19
U盘实现流程跟踪分析02
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />   二、追踪USB大容量设备的实现...
nthq2004 2010-04-27 21:51
U盘实现流程跟踪分析01
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />   一、追踪USB大容量设备的实现...
EE直播间
更多
我要评论
1
8
关闭 站长推荐上一条 /3 下一条