纬图虚拟仪器论坛

 找回密码
 立即注册
搜索
查看: 20268|回复: 5

SD卡程序调试问题

[复制链接]
发表于 2012-8-26 23:37:56 | 显示全部楼层 |阅读模式
本帖最后由 wdluo 于 2012-8-27 00:19 编辑

今天用S3C2440调试裸机的SD卡驱动,移植FATFS R0.9版本的文件系统,移植完毕后发现一个问题,这个程序读写2G的SD卡完全没问题,但是当我使用4G的金士顿SD卡的时候程序提示找不到文件系统,于是我单步调试到ff.c文件里面的check_fs()函数,该函数源码如下:
  1. /*-----------------------------------------------------------------------*/
  2. /* Load a sector and check if it is an FAT Volume Boot Record            */
  3. /*-----------------------------------------------------------------------*/

  4. static
  5. BYTE check_fs (        /* 0:FAT-VBR, 1:Valid BR but not FAT, 2:Not a BR, 3:Disk error */
  6.         FATFS *fs,        /* File system object */
  7.         DWORD sect        /* Sector# (lba) to check if it is an FAT boot record or not */
  8. )
  9. {
  10.         if (disk_read(fs->drv, fs->win, sect, 1) != RES_OK)        /* Load boot record */
  11.                 return 3;
  12.         if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55)                /* Check record signature (always placed at offset 510 even if the sector size is >512) */
  13.                 return 2;

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

  18.         return 1;
  19. }
复制代码
在该函数里我单步运行,第一个和第二个if语句都没有问题,也就是说第0扇区的数据读取和扇区分区结束标志检查都是正确的,但是文件系统的类型检查失败,也就是找不到“FAT”这个字符串,首先我怀疑是文件系统的问题,于是将SD卡取出并在电脑上格式化后在读取,结果都是一样的,诡异的是电脑能正确识别SD卡,说明SD卡上的文件系统是有的,于是我就Google,后来找到了一篇关于SD分区的介绍,简单的说就是4G的SD卡有MBR分区的问题,第0扇区的数据不是文件系统的数据,而是MBR数据,根据网上的介绍,说在物理扇区0的0X1C6处会存储保留扇区数的数据,于是我用HxD_Hex_Editor软件查看扇区0的数据发现数据不对,下面是我用HxD_Hex_Editor查看我SD卡扇区0的数据:
1.jpg
由这个第0扇区的数据发现在0x1C6这里的数据为0,理论上说就是没有保留扇区,物理扇区和逻辑扇区应该是重合的,但实际上并不是这样子,在第0扇区里面没有文件系统的相关数据,比如
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;
这两条语句就检查不到文件系统,但是电脑能识别SD卡,说明SD的文件系统一定是存在的,但具体在哪里呢?我用这个软件的搜索功能搜索“FAT”字符串,结果在第63扇区找到了这个字符串,也就是真正的文件系统,如下图所示:
2.jpg
分析这个数据发现这才是我们真正需要的数据,而且数据也是正确的,所以现在的问题是如何让程序能自动识别这个逻辑分区。
首先我用一个最笨的方法,那就是在diskio.c文件里面的读写SD卡函数里面将扇区参数直接加上63,这样就实现了63个扇区的偏移,改写后的程序如下:
  1. DRESULT disk_read (
  2.         BYTE drv,                /* Physical drive nmuber (0..),only 0 implemented */
  3.         BYTE *buff,                /* Data buffer to store read data */
  4.         DWORD sector,        /* Sector address (LBA) */
  5.         BYTE count                /* Number of sectors to read (1..255) */
  6. )
  7. {
  8.         DRESULT res;        
  9.         if ((drv!=0) || (buff==0))        return RES_PARERR;//more check needed
  10.         if(count<2)
  11.                 res=Read_One_Block(sector+63,buff);
  12.         else
  13.         {
  14.                 res=Read_Mult_Block(sector+63,count,buff);
  15.         }        
  16.         if(res)
  17.                 return RES_OK;
  18.         else
  19.                 return RES_ERROR;
  20. }
复制代码
写函数也做相同的处理,编译程序,下载运行...
正确了!!文件读写正确了!!运行效果如下图:
4.jpg
看来确实是那个MBR的问题,现在的疑问是为什么在0x1C6那里没有扇区偏移的数据?难道是存储在其他地方的?还有就是,就算是找到了这个数据的存储地址,那文件系统该如何处理?FATFS是否可以自动处理?这就等到我下一步的调试结果吧。
上传一个查看磁盘数据的软件: HxD_Hex_Editor_CHS_1[1].7.7.0.rar (852.95 KB, 下载次数: 89)
回复

使用道具 举报

 楼主| 发表于 2012-8-27 01:04:19 | 显示全部楼层
再次看了下FATFS的源码,在ff.c文件的chk_mounted()函数中有这么一段程序:
  1.         /* Search FAT partition on the drive. Supports only generic partitionings, FDISK and SFD. */
  2.         fmt = check_fs(fs, bsect = 0);                /* Load sector 0 and check if it is an FAT-VBR (in SFD) */
  3.         if (LD2PT(vol) && !fmt) fmt = 1;        /* Force non-SFD if the volume is forced partition */
  4.         if (fmt == 1) {                                                /* Not an FAT-VBR, the physical drive can be partitioned */
  5.                 /* Check the partition listed in the partition table */
  6.                 pi = LD2PT(vol);
  7.                 if (pi) pi--;
  8.                 tbl = &fs->win[MBR_Table + pi * SZ_PTE];/* Partition table */
  9.                 if (tbl[4]) {                                                /* Is the partition existing? */
  10.                         bsect = LD_DWORD(&tbl[8]);                /* Partition offset in LBA */
  11.                         fmt = check_fs(fs, bsect);                /* Check the partition */
  12.                 }
  13.         }
  14.         if (fmt == 3) return FR_DISK_ERR;
  15.         if (fmt) return FR_NO_FILESYSTEM;                /* No FAT volume is found */
复制代码
分析该程序发现,if(fmt == 1)这个判断里面的代码就是实现检查逻辑扇区在什么物理扇区的代码,bsect = LD_DWORD(&tbl[8]);  /* Partition offset in LBA */这句程序就是获取第1个逻辑扇区的实际物理扇区号,又根据这句:tbl = &fs->win[MBR_Table + pi * SZ_PTE];/* Partition table */和#define MBR_Table   446 /* MBR: Partition table offset (2) */可知,该逻辑扇区的起始扇区号就存储在0扇区的446+8处,也就是0x1C6,如下图所示:
5.jpg
由该图可看出该地址数据为0,而不是理论上的63,因此该文件系统无法正确获取逻辑分区所在的起始扇区,因此出现无法正确检测到文件系统的情况,这是什么原因我不是很清楚,暂且认为是SD卡本身的原因,具体解决方法后面调试再说......
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-9-4 23:27:06 | 显示全部楼层
上传移植好了的代码: LCD_FATFS.rar (3.23 MB, 下载次数: 117)
回复 支持 反对

使用道具 举报

发表于 2012-10-10 14:37:17 | 显示全部楼层

回帖奖励 +2

回复 支持 反对

使用道具 举报

发表于 2012-11-30 21:57:38 | 显示全部楼层
目前也在弄这个,也下了论坛的那个版本,也是很多问题,原来是ads的工程,用的是ucfs,但是版本很低无法识别2g以上的,而且程序本身,也没有对sd卡区分,正好搜到有这个2440的fatfs,就借用了底层的部分,没有移植上层应用函数的部分。结果连以前的卡也读写不了,到时可以识别了。
回复 支持 反对

使用道具 举报

发表于 2013-1-14 14:42:05 | 显示全部楼层
非常感谢楼主!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|纬图虚拟仪器

GMT+8, 2024-12-22 01:14 , Processed in 0.672886 second(s), 22 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表