野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 17494|回复: 8

SDIO FatFs文件系统移植 程序卡死在f_cloce()函数

[复制链接]
发表于 2017-2-10 15:09:57 | 显示全部楼层 |阅读模式
本帖最后由 艺歌ly 于 2017-2-10 15:13 编辑

近日对于SD卡移植FatFs文件系统(版本R0.12b),进行文件系统挂、文件写入、文件读取测试时,发现在文件写入之后关闭文件会卡死在f_close()函数中,没有返回值,再次复位时会挂载文件系统失败(FR_NOT_READY)。使用野火的例程也出现同样问题。调用函数流程大致为f_mount->f_open()->f_close->f_open()->f_close->f_mount。
  1.                          摘自野火例程《SDIO—FatFs移植与读写测试》


  2.          /*----------------------- 文件系统测试:写测试 -----------------------------*/
  3.         /* 打开文件,如果文件不存在则创建它 */
  4.         printf("\r\n****** 即将进行文件写入测试... ******\r\n");        
  5.         res_sd = f_open(&fnew, "0:FatFs读写测试文件.txt",FA_CREATE_ALWAYS | FA_WRITE );                               //后来发现是FA_CREATE_ALWAYS参数出现问题
  6.         if ( res_sd == FR_OK )
  7.         {
  8.                 printf("》打开/创建FatFs读写测试文件.txt文件成功,向文件写入数据。\r\n");
  9.     /* 将指定存储区内容写入到文件内 */
  10.                 res_sd=f_write(&fnew,WriteBuffer,sizeof(WriteBuffer),&fnum);
  11.     if(res_sd==FR_OK)
  12.     {
  13.       printf("》文件写入成功,写入字节数据:%d\n",fnum);
  14.       printf("》向文件写入的数据为:\r\n%s\r\n",WriteBuffer);
  15.     }
  16.     else
  17.     {
  18.       printf("!!文件写入失败:(%d)\n",res_sd);
  19.     }   
  20.                 /* 不再读写,关闭文件 */



  21.     f_close(&fnew);                         //卡死在这里!!!!!




  22.         }
  23.         else
  24.         {        
  25.                 LED_RED;
  26.                 printf("!!打开/创建文件失败。\r\n");
  27.         }
复制代码

通过Debug发现,程序在写入测试中的f_close()函数中出现问题,经过调试发现问题出在f_close()函数中调用的disk_read()和disk_write()两个函数,即f_close()->f_sync()->move_window()->disk_read()和f_close()->f_sync()->sync_fs()->sync_window()->disk_write()之间,程序卡死在disk_write()的等待传输完成部分,等待很长时间都未见完成。这两个disk_read()和disk_write()是紧接着的两个SD卡读写操作。后来发现在disk_read()和disk_write()之间需要加入500次以上的循环延时才能正常运行,否则程序卡死在disk_write()的等待传输完成部分。

  1.                        摘自FatFs源程序《ff.c》


  2. FRESULT f_sync (
  3.         FIL* fp                /* Pointer to the file object */
  4. )
  5. {
  6.         FRESULT res;
  7.         FATFS *fs;
  8.         DWORD tm;
  9.         BYTE *dir;
  10.         DEF_NAMBUF

  11.         res = validate(&fp->obj, &fs);        /* Check validity of the file object */
  12.         if (res == FR_OK) {
  13.                 if (fp->flag & FA_MODIFIED) {        /* Is there any change to the file? */
  14. #if !_FS_TINY
  15.                         if (fp->flag & FA_DIRTY) {        /* Write-back cached data if needed */
  16.                                 if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) LEAVE_FF(fs, FR_DISK_ERR);
  17.                                 fp->flag &= (BYTE)~FA_DIRTY;
  18.                         }
  19. #endif
  20.                         /* Update the directory entry */
  21.                         tm = GET_FATTIME();                                /* Modified time */
  22. #if _FS_EXFAT
  23.                         if (fs->fs_type == FS_EXFAT) {
  24.                                 res = fill_fat_chain(&fp->obj);        /* Create FAT chain if needed */
  25.                                 if (res == FR_OK) {
  26.                                         DIR dj;

  27.                                         INIT_NAMBUF(fs);
  28.                                         res = load_obj_dir(&dj, &fp->obj);        /* Load directory entry block */
  29.                                         if (res == FR_OK) {
  30.                                                 fs->dirbuf[XDIR_Attr] |= AM_ARC;                                /* Set archive bit */
  31.                                                 fs->dirbuf[XDIR_GenFlags] = fp->obj.stat | 1;        /* Update file allocation info */
  32.                                                 st_dword(fs->dirbuf + XDIR_FstClus, fp->obj.sclust);
  33.                                                 st_qword(fs->dirbuf + XDIR_FileSize, fp->obj.objsize);
  34.                                                 st_qword(fs->dirbuf + XDIR_ValidFileSize, fp->obj.objsize);
  35.                                                 st_dword(fs->dirbuf + XDIR_ModTime, tm);                /* Update modified time */
  36.                                                 fs->dirbuf[XDIR_ModTime10] = 0;
  37.                                                 st_dword(fs->dirbuf + XDIR_AccTime, 0);
  38.                                                 res = store_xdir(&dj);        /* Restore it to the directory */
  39.                                                 if (res == FR_OK) {
  40.                                                         res = sync_fs(fs);
  41.                                                         fp->flag &= (BYTE)~FA_MODIFIED;
  42.                                                 }
  43.                                         }
  44.                                         FREE_NAMBUF();
  45.                                 }
  46.                         } else
  47. #endif
  48.                         {
  49.                                 DWORD i = 500;

  50.                                 
  51.                                 
  52.                                 res = move_window(fs, fp->dir_sect);             //此函数最后是一个disk_read()函数



  53.                                 if (res == FR_OK) {

  54.                                         dir = fp->dir_ptr;
  55.                                         dir[DIR_Attr] |= AM_ARC;                                                /* Set archive bit */
  56.                                         st_clust(fp->obj.fs, dir, fp->obj.sclust);                /* Update file allocation info  */
  57.                                         st_dword(dir + DIR_FileSize, (DWORD)fp->obj.objsize);        /* Update file size */
  58.                                         st_dword(dir + DIR_ModTime, tm);                                /* Update modified time */
  59.                                         st_word(dir + DIR_LstAccDate, 0);
  60.                                         fs->wflag = 1;
  61.                                        
  62.                                        

  63.                                         while(i--);                         //两者之间需要加入500次以上循环延时才能正常运行
  64.                                        
  65.                                        
  66.                                        
  67.                                         res = sync_fs(fs);                       //此函数开头是一个disk_write()函数



  68.                                         fp->flag &= (BYTE)~FA_MODIFIED;
  69.                                 }
  70.                         }
  71.                 }
  72.         }

  73.         LEAVE_FF(fs, res);
  74. }
复制代码

进一步的测试发现,这个情况与f_open()函数的第三个参数Mode flags有关。野火例程中使用的是FA_CREATE_ALWAYS,将此参数改为FA_OPEN_ALWAYS则问题解决,程序正常运行。FA_CREATE_ALWAYS是文件存在的情况下进行覆盖,FA_OPEN_ALWAYS在文件不存在的情况下才创建文件。因此估计是对文件的覆盖操作出现的问题。不知道这种情况有没有人遇到过,我换了两张不同的SD卡都是同样的情况。本人对于FatFs及SD卡操作了解不多,想请教一下火哥和各位大神这种情况是什么原因?虽然目前问题已经解决了,但是不知道原因感觉不踏实。
另外,鉴于这种问题,建议火哥将FA_CREATE_ALWAYS参数改为FA_OPEN_ALWAYS更为稳妥。
第一次发帖,有什么不当之处请各位大大指正。




回复

使用道具 举报

发表于 2017-2-10 15:12:29 | 显示全部楼层
研究的好深入,帮顶。
回复 支持 反对

使用道具 举报

发表于 2017-2-10 15:13:14 | 显示全部楼层
FA_CREATE_ALWAYS 例程里就是为了总是创建一个新文件,重新测试。我们这边测试不会有问题啊

你把前面的每一个文件操作返回的res都打印出来看看
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-2-10 15:24:47 | 显示全部楼层
本帖最后由 艺歌ly 于 2017-2-10 15:26 编辑
flyleaf 发表于 2017-2-10 15:13
FA_CREATE_ALWAYS 例程里就是为了总是创建一个新文件,重新测试。我们这边测试不会有问题啊

你把前面的 ...

原例程运行到f_close()会卡死,并没有返回结果,在f_close()之前的操作如果能挂载成功的话返回都是FR_OK,但是复位后经常是挂载不成功,返回FR_NOT_READY。程序始终是卡死和挂载不成功这两种情况。每一步返回值都有打印测试,只有这两种情况。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-2-10 15:38:32 | 显示全部楼层
flyleaf 发表于 2017-2-10 15:13
FA_CREATE_ALWAYS 例程里就是为了总是创建一个新文件,重新测试。我们这边测试不会有问题啊

你把前面的 ...

很奇怪,SPI Flash的文件系统没出现这个问题。有可能是SD卡驱动程序的问题。
回复 支持 反对

使用道具 举报

发表于 2017-2-10 16:04:58 | 显示全部楼层
艺歌ly 发表于 2017-2-10 15:38
很奇怪,SPI Flash的文件系统没出现这个问题。有可能是SD卡驱动程序的问题。

SDIO—FatFs移植与读写测试.zip (1.25 MB, 下载次数: 153) 不知道你用的是哪个例程,刚刚我直接用这个测没有问题:
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-2-10 18:16:57 | 显示全部楼层
flyleaf 发表于 2017-2-10 16:04
不知道你用的是哪个例程,刚刚我直接用这个测没有问题:

360截图20170210181502323.jpg
还是不行,刚擦写完成和复位几次的结果。
可能是SD卡或其它个别原因吧。
回复 支持 反对

使用道具 举报

发表于 2017-2-10 19:25:04 | 显示全部楼层
艺歌ly 发表于 2017-2-10 18:16
还是不行,刚擦写完成和复位几次的结果。
可能是SD卡或其它个别原因吧。

stm32是有点挑卡,但只要是能格式化的,都没有问题啊
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-2-10 20:36:51 | 显示全部楼层
flyleaf 发表于 2017-2-10 19:25
stm32是有点挑卡,但只要是能格式化的,都没有问题啊

没关系了,现在也算解决了。当是反馈一下这个bug吧。
回复 支持 反对

使用道具 举报

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

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-11-23 15:21 , Processed in 0.038183 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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