打印

可怕的问题:FATFS f_open() 返回可怕的 FR_NO_FILESYS

[复制链接]
11766|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
BBSTOM|  楼主 | 2013-9-11 15:29 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
可怕的问题:FATFS  f_open() 返回可怕的 FR_NO_FILESYS

SDHC KINGSTON的4G卡 ,在电脑上已经格式化,里面有ABC.TXT文本文件。

移植好的FATFS文件系统在 万利的EK-STM32F 开发板上 对写SD卡。
   
   disk_sta=disk_initialize(0);//disk_status       
    f_mount(0, &fatfs[0]);  
上面两句都运行正常!

    /* Open source file on the drive 1 */
   res = f_open(&fsrc, "0:/ABC.TXT", FA_CREATE_NEW | FA_READ);
就返回可怕的FR_NO_FILESYSTEM

从网上找来同样的问题的帖子:


SD卡sector0读出来只有最后两个字节是 55 AA,中间也有几个数据,其他的都是00,check_fs函数返回 FR_NO_FILESYSTEM 无可用的文件系统。
网上查了一下FAT系统的资料,发现物理扇区0(MBR)并不是逻辑扇区0,根据第一个sector读出的数据,我的物理扇区的地址应该是0x61而不是0。
后来仔细查了一下FATFS的源码,发现只支持 FDISK 和 SFD 格式的FAT系统,于是我猜想如果用fdisk格式化,MBR的物理扇区和逻辑扇区地址就都是0了。
然后在linux下用FDISK又格式化了一把,发现情况还是一样。
不知道各位大侠的SD卡是用什么格式化的?



我现在在裸机下移植fatfs,出现和你差不多的问题,麻烦楼主能看看
fmt = check_fs(fs, bsect = 0);                // Check sector 0 if it is a VBR
//fmt = check_fs(fs, 243);
        if (fmt == 1) {                                                // Not an FAT-VBR, the disk may be partitioned
                // Check the partition listed in top of the partition table
                tbl = &fs->win;        // Partition table
                if (tbl) {                                                                        // Is the partition existing?
                        bsect = LD_DWORD(&tbl);                                        // Partition offset in LBA
                        fmt = check_fs(fs, bsect);                                        // Check the partition
                        //fmt = check_fs(fs, 0);
                }
        }
第一句话fmt = check_fs(fs, bsect = 0);是去读sd卡的MBR,即第0扇区,数据正常,且根据里面的数据经过bsect = LD_DWORD(&tbl);这句话计算正确得到启动扇区的位置(243),然后fmt = check_fs(fs, bsect);这句话就是去读这个启动扇区内的数据,这里面的数据
非常重要,就像我们电脑的C盘,但是返回来全部是0,导致fatfs失败。然后同一张卡在另一块板子的代码上测试正常,里面的数据也正常。
那么可以说明一点的是,既然可以读0扇区数据正常那么说明sd的底层读函数是对的,那么为什么读不出来第243扇区的数据?
同事怀疑是sd卡初始化中设置成了只能读一次,那么我一开始就读第243扇区,也是返回全0.这就郁闷了。在另一块板子的代码上测试,一开始读243扇区的数据是正常的。
最后,我将sd卡格式化,用winhex查看其扇区内容,发现0扇区和243扇区的数据没变。
以上是我调试的总结以及遇到的问题,希望楼主能耐心看看,谢谢!
        

这个问题我也发现了
我的物理扇区对应为8192扇区
也是如果先读0扇区,再读8192扇区返回都是0
但是如果先读8192扇区,就会返回正确数据
后来我调试发现,连续读两次8192扇区,第一次返回正确数据,第二次就全是0
求解释!


//

FR_NO_FILESYSTEM  问题:

提示没有在你的目标存储器上建立文件系统,试试res = f_mkfs(0,0,2048);这里的2048是2048 bytes,
指的是你的目标存储器的扇区大小 也有可能是你没有执行注册磁盘空间的操作,试试res = f_mount(0,&fs);

我在读写TF卡的时候也出现过这样的问题,我的解决方式是将卡用卡槽插到PC机上,然后格式化一下,我格式化选择的是FAT格式。

试试用F_MKFS函数格式化一下
未格式化为Fat格式,先在电脑里格式化或者用Fatfs自带的格式化函数格式化SD.记得要格式化为Fatfs支持的格式

记得要把文件系统变量放到main函数的外面,比如工作区的变量,文件指针变量等。不这样做会出现一些错误,改了就好。我移植的时候没注意,就一直停顿这里很久,原因不明。

说明你没有格式化,首先需要执行f_mkfs()函数,此步骤为建立FAT相关的一些表。只需要执行一次就可以了,以后再运行程序不需执行。


在FATFS中经常用到chk_mount这个函数,主要是对物理驱动器检测它的可用性,即磁盘现在是否可用,避免了磁盘中途掉电的情况,在其中有这么一段程序


        fmt = check_fs(fs, bsect = 0);                // Check sector 0 if it is a VBR /可用的分区记录
        if (fmt == 1) {                                                // Not an FAT-VBR, the disk may be partitioned /
                //结束符正确,确不是FAT系统,则读取下一个分区的数据,看是否是有效的结束符和FAT系统
                // Check the partition listed in top of the partition table /
                tbl = &fs->win[MBR_Table + LD2PT(vol) * SZ_PTE];// Partition table /下一个分区属性的16字节存储指针
                if (tbl[4]) {                                                                        // Is the partition existing? /系统ID对于FAT32为0x01,未用是为0
                        bsect = LD_DWORD(&tbl[8]);                                        // Partition offset in LBA /分区偏移地址
                        fmt = check_fs(fs, bsect);        //root record                                // Check the partition /这一句不懂了
                }
        }       
这一次它是要检测什么的??

后来想了一想,对于我们的硬盘,大多是只有一个分区的,但是有的可能会有多个分区,而对于每一个分区而言,他都有一个MBR区,又称为伪MBR区,存储了这一个分区的引导程序,以及分区的信息,这样的话,如果第一个分区不是FAT系统,我们就查找是否又下一个分区,如果有的话,就开始对下一分区的判断……

但是为什么它只检测了两个分区呢,可能后面还有分区呢???

if (fmt == 3) return FR_DISK_ERR;
if (fmt) return FR_NO_FILESYSTEM; // No FAT volume is found /
//两次检测之后还不是FAT系统,就返回错误



我的理解是:
在一些SD1.0中,物理0扇区就是逻辑0扇区,0扇区就是DBR,没有MBR,这种情况也就不存在分区,第一个fmt = check_fs(fs, bsect = 0);会返回0,
因为check_fs里的第三个或第四个if判断会检测到DBR里面的FAT系统标识字符串,其中一个会返回0,fmt=0,fmt = check_fs(fs, bsect);就不会执行了
*********************************************
if (disk_read(fs->drive, fs->win, sect, 1) != RES_OK) // Load boot record  
return 3;
if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55) // Check record signature (always placed at offset 510 even if the sector size is >512)  
return 2;

if ((LD_DWORD(&fs->win[BS_FilSysType]) & 0xFFFFFF) == 0x544146) // Check "FAT" string  
return 0;
if ((LD_DWORD(&fs->win[BS_FilSysType32]) & 0xFFFFFF) == 0x544146)
return 0;

return 1;
************************************************

而在一些有MBR的sd卡中物理0扇区是MBR,mbr里有DBR的偏移信息,执行fmt = check_fs(fs, bsect = 0);的时候,第一个和第二个if会通过,
但是mbr里面没有fat标识字符串所以第三个和第四个if不会过,返回1,fmt=1就会执行fmt = check_fs(fs, bsect);
其中bsect是从mbr里读出来的逻辑0扇区偏移量,既DBR所在扇区,这次执行就同上面读DBR一样,会再第三个或第三个if返回0.


楼上基本上说全了。
chaN的驱动是针对sd,ata,usb,nand的,不单单是sd。我的sd2.0是没有MBR的,0扇区就是DBR。而PC硬盘ata的MBR就在0扇区。
我们重装PC的时候硬盘是可以选择NTFS和FAT等格式。
在有MBR的前提下,就有DPT,紧接MBR引导代码是DPT和“55AA”,DBR是在偏移X扇区里,X就是代码的tbl[8]的双字(4字节),也就是DPT的OFFSET 8~11。
假设有4分区,那么只要第一次检查0扇区是不是DBR,如果不是就检查第二次(只需检查1次即可,无需检查多次,目的是验证是否是FAT),检查偏移X扇区。
执行check_fs(fs, bsect);后返回0,则说明第4分区DBR就在X扇区,验证成功,返回!0则错误。

以上个人见解,不对请及时纠正。
沙发
cjhk| | 2013-9-11 18:56 | 只看该作者
首先  需要谢谢楼主的共享经验    这一块   我虽然了解的  不多   但是   感觉楼主很给力   先谢谢了  楼主

使用特权

评论回复
板凳
cjhk| | 2013-9-11 18:56 | 只看该作者
**  需要好好琢磨琢磨    毕竟这一块   还是实际测试测试   遇到问题后    将问题解决了   才能最终证明你的思路  

使用特权

评论回复
地板
BBSTOM|  楼主 | 2013-9-12 08:19 | 只看该作者
~ding

使用特权

评论回复
5
re张风| | 2013-9-12 17:32 | 只看该作者
我最开始测试时,也是这样的问题,但我是这样子进行调试的供你参考一下:
在文件系统测试代码中,通过串口打印出读SD卡时,读的扇区号,再用STM32F103的SDIO例子,指定去读SD的那个扇区,把所读出来的数据全输出来,看看它的几个55AA数据是否是对的。再进行分析,肯定能找到问题出在那里!

使用特权

评论回复
6
puchuang| | 2013-9-12 19:07 | 只看该作者
期待楼主  能够将解决问题的方法   共享一下   谢谢了

使用特权

评论回复
7
myxiaonia| | 2013-9-13 10:08 | 只看该作者
用电脑上的winhex去看下你的sd卡的0扇区是怎么回事
看看是不是mbr,当然 也得了解下这个mbr的结构
fat文件系统原理总得知道个大概吧
光是拿来用是不行的,我看到很多人拿个例程搞搞就算调通了,网上好多用stm32官方库就搞定了u盘主机模式,实际上可能代码不看,这怎么行

使用特权

评论回复
8
ccczzzyyy| | 2017-6-22 11:06 | 只看该作者
不知道现在还有没有在关注这个问题。我用check_fs去读取0号扇区的数(这个地方我不知道是不是这个意思),我用winhex看见我SDHC卡里面第一个扇区最后两位是55AA,但是走程序读0号扇区的数完全不对,和我在winhex上看到的完全不一样,当然最后两位也不是55AA。不知道有没有人发现这个情况。

使用特权

评论回复
9
sm05270321| | 2017-7-6 17:27 | 只看该作者
楼主现在解决了吗

使用特权

评论回复
10
sm05270321| | 2017-7-6 17:28 | 只看该作者
可以加下QQ交流下吗、我QQ972463893

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

56

主题

282

帖子

1

粉丝