原创 智林STM32开发板上的FatFS移植过程分析(七)

2010-3-19 22:28 4882 6 6 分类: MCU/ 嵌入式

https://static.assets-stash.eet-china.com/album/old-resources/2010/3/19/4d5896ca-ef95-4cb2-9a40-906137442cad.rar有智林STM32开发板和SD卡的朋友可以下载测试。


<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 


八、读文件执行流程分析续


上次的分析到了f_open()函数这个层次,到最后函数根据path所指向的文件填充了File信息结构体,最关键的信息包括文件目录项所在扇区、文件目录项指针、文件的起始簇号、文件读写指针当前位置、文件的访问模式等。


 


l         执行函数:f_read(&FileInf,(void *)FileBuf,500,&ByteRead);


FileBuf是用户提供的缓冲区,从文件读取的数据拷贝到它,500是每次想要读取的字节数,ByteRead是实际读出的数目。


进入函数,先执行remain = fp->fsize - fp->fptr;remain是文件从当前位置开始算还剩下的字节数。if (btr > remain) btr = (UINT)remain;    如果需读取数》实际剩余字节数,则改为把所有剩下的数字读完。


for ( ;  btr;   rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) {


//这里这个rcnt是每次能够读取的字节数,读取一次以后,用户缓冲区指针、文件读写指针都往前移动rcnt个季节,实际读取数加rcnt,剩下需要读取的数目减去rcnt


              if ((fp->fptr % SS(fp->fs)) == 0) {                    第一次读文件时,指针指向0


                     if (fp->csect >= fp->fs->csize) {         第一次读文件csect=0xff。以后再读时,这个条件就不满足了。除非文件大于4K


                            clst = (fp->fptr == 0) ?  这句执行完成后clst=文件数据区的第一簇


                                   fp->org_clust : get_fat(fp->fs, fp->curr_clust);


 


                            fp->curr_clust = clst;           更新文件所指向的当前簇


                            fp->csect = 0;        文件的当前扇区相对号为0.


         }


sect = clust2sect(fp->fs, fp->curr_clust);将簇转换为实际的扇区号,在加上扇区相对号,就是实际扇区编号。


                     sect += fp->csect;


                     cc = btr / SS(fp->fs);  计算出需要读取的扇区的数目


                     if (cc) {   }这是大于或等于一个扇区的情况。


 


                     if (fp->dsect != sect) {         将文件当前扇区的内容读入文件的文件信息结构体的缓冲区内,并更新数据扇区号。


                            if (disk_read(fp->fs->drive, fp->buf, sect, 1) != RES_OK)


                                   ABORT(fp->fs, FR_DISK_ERR);


                     }


                     fp->dsect = sect;


                     fp->csect++;       调整当前相对扇区号指向下一个扇区。


             


rcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs));      这就是每次实际读取的数目。


if (rcnt > btr) rcnt = btr;  当小于512字节时,强制等于用户规定的字节数。


mem_cpy(rbuff, &fp->buf[fp->fptr % SS(fp->fs)], rcnt); 执行这句以后将rcnt大小的字节从文件扇区缓冲拷贝到用户缓冲区。拷贝位置是从文件指针相对应的地方开始。


 


rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt这句话执行一遍,文件指针已经指向500btr已经等于0,函数接下来就会跳出循环。


第一次读文件执行完成后,主要改变了三个参数:文件指针的位置(指向500)、文件的当前扇区号(1号)、文件的数据扇区号(指向刚刚读入的扇区)。


 


l        在上一次的基础上再次执行f_read(&FileInf,(void *)FileBuf,500,&ByteRead);


for ( ;  btr;   rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) {


              if ((fp->fptr % SS(fp->fs)) == 0) {             第二次第一轮读文件时,指针指向500


                              }  这段程序就不会被执行。


             


rcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs));      这是第二次实际读取数目,12字节


if (rcnt > btr) rcnt = btr;  当需读小于一个扇区剩余字节时,强制等于用户规定的字节数。


mem_cpy(rbuff, &fp->buf[fp->fptr % SS(fp->fs)], rcnt); 执行这句以后将rcnt大小的字节从文件扇区缓冲拷贝到用户缓冲区。拷贝位置是从文件指针相对应的地方开始


rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt这句话执行一遍,文件指针已经指向512btr已经等于488512减去刚刚读的12字节)函数接下来重新执行。


 


if ((fp->fptr % SS(fp->fs)) == 0) {                    第二次第二轮读文件时,指针指向512


                              }  这段程序又被执行。


如果当前扇区没有超出当前簇的范围,if (fp->csect >= fp->fs->csize) {}这段程序不会执行。


                     sect = clust2sect(fp->fs, fp->curr_clust);    /* Get current sector */


                     sect += fp->csect;  //取下一扇区的绝对扇区号


                     cc = btr / SS(fp->fs);   


                     if (fp->dsect != sect) {         /* 数据扇区不是当前扇区 */


                            if (disk_read(fp->fs->drive, fp->buf, sect, 1) != RES_OK) 读入当前扇区数据                                ABORT(fp->fs, FR_DISK_ERR);               }


                     fp->dsect = sect; //数据扇区号更新


                     fp->csect++;         //当前扇区号更新。


              rcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs));      /* 读入的实际数=512-0=512 */


              if (rcnt > btr) rcnt = btr; 由于只要求读488个字节,故实际读入数修改。


l        修改参数,再次执行f_read(&FileInf,(void *)FileBuf,800,&ByteRead);


读入500字节后,文件指针的位置(指向500)、文件的当前扇区号(1号)、文件的数据扇区号(绝对扇区号,相对为0)。如果再读800字节,实际跨度为0-23个扇区。


在调试的过程中,出了一个较大的问题,由于我刚开始定义的FileBuf只有512字节,现在要读取800字节,结果把很多有用的数据都覆盖了,这就是指针带来的缓冲区溢出问题吧。


 


 


 

文章评论0条评论)

登录后参与讨论
我要评论
0
6
关闭 站长推荐上一条 /2 下一条