小学生
最后登录1970-1-1
在线时间 小时
注册时间2017-2-10
|
本帖最后由 艺歌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。
- 摘自野火例程《SDIO—FatFs移植与读写测试》
- /*----------------------- 文件系统测试:写测试 -----------------------------*/
- /* 打开文件,如果文件不存在则创建它 */
- printf("\r\n****** 即将进行文件写入测试... ******\r\n");
- res_sd = f_open(&fnew, "0:FatFs读写测试文件.txt",FA_CREATE_ALWAYS | FA_WRITE ); //后来发现是FA_CREATE_ALWAYS参数出现问题
- if ( res_sd == FR_OK )
- {
- printf("》打开/创建FatFs读写测试文件.txt文件成功,向文件写入数据。\r\n");
- /* 将指定存储区内容写入到文件内 */
- res_sd=f_write(&fnew,WriteBuffer,sizeof(WriteBuffer),&fnum);
- if(res_sd==FR_OK)
- {
- printf("》文件写入成功,写入字节数据:%d\n",fnum);
- printf("》向文件写入的数据为:\r\n%s\r\n",WriteBuffer);
- }
- else
- {
- printf("!!文件写入失败:(%d)\n",res_sd);
- }
- /* 不再读写,关闭文件 */
- f_close(&fnew); //卡死在这里!!!!!
- }
- else
- {
- LED_RED;
- printf("!!打开/创建文件失败。\r\n");
- }
复制代码
通过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()的等待传输完成部分。
- 摘自FatFs源程序《ff.c》
- FRESULT f_sync (
- FIL* fp /* Pointer to the file object */
- )
- {
- FRESULT res;
- FATFS *fs;
- DWORD tm;
- BYTE *dir;
- DEF_NAMBUF
- res = validate(&fp->obj, &fs); /* Check validity of the file object */
- if (res == FR_OK) {
- if (fp->flag & FA_MODIFIED) { /* Is there any change to the file? */
- #if !_FS_TINY
- if (fp->flag & FA_DIRTY) { /* Write-back cached data if needed */
- if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) LEAVE_FF(fs, FR_DISK_ERR);
- fp->flag &= (BYTE)~FA_DIRTY;
- }
- #endif
- /* Update the directory entry */
- tm = GET_FATTIME(); /* Modified time */
- #if _FS_EXFAT
- if (fs->fs_type == FS_EXFAT) {
- res = fill_fat_chain(&fp->obj); /* Create FAT chain if needed */
- if (res == FR_OK) {
- DIR dj;
- INIT_NAMBUF(fs);
- res = load_obj_dir(&dj, &fp->obj); /* Load directory entry block */
- if (res == FR_OK) {
- fs->dirbuf[XDIR_Attr] |= AM_ARC; /* Set archive bit */
- fs->dirbuf[XDIR_GenFlags] = fp->obj.stat | 1; /* Update file allocation info */
- st_dword(fs->dirbuf + XDIR_FstClus, fp->obj.sclust);
- st_qword(fs->dirbuf + XDIR_FileSize, fp->obj.objsize);
- st_qword(fs->dirbuf + XDIR_ValidFileSize, fp->obj.objsize);
- st_dword(fs->dirbuf + XDIR_ModTime, tm); /* Update modified time */
- fs->dirbuf[XDIR_ModTime10] = 0;
- st_dword(fs->dirbuf + XDIR_AccTime, 0);
- res = store_xdir(&dj); /* Restore it to the directory */
- if (res == FR_OK) {
- res = sync_fs(fs);
- fp->flag &= (BYTE)~FA_MODIFIED;
- }
- }
- FREE_NAMBUF();
- }
- } else
- #endif
- {
- DWORD i = 500;
-
-
- res = move_window(fs, fp->dir_sect); //此函数最后是一个disk_read()函数
- if (res == FR_OK) {
- dir = fp->dir_ptr;
- dir[DIR_Attr] |= AM_ARC; /* Set archive bit */
- st_clust(fp->obj.fs, dir, fp->obj.sclust); /* Update file allocation info */
- st_dword(dir + DIR_FileSize, (DWORD)fp->obj.objsize); /* Update file size */
- st_dword(dir + DIR_ModTime, tm); /* Update modified time */
- st_word(dir + DIR_LstAccDate, 0);
- fs->wflag = 1;
-
-
- while(i--); //两者之间需要加入500次以上循环延时才能正常运行
-
-
-
- res = sync_fs(fs); //此函数开头是一个disk_write()函数
- fp->flag &= (BYTE)~FA_MODIFIED;
- }
- }
- }
- }
- LEAVE_FF(fs, res);
- }
复制代码
进一步的测试发现,这个情况与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更为稳妥。
第一次发帖,有什么不当之处请各位大大指正。
|
|