OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 15625|回复: 9

stm32移植fatfs上电复位前两次不能正确打开文件解决方法。

[复制链接]

2

主题

15

帖子

0

精华

新手上路

积分
47
金钱
47
注册时间
2012-11-11
在线时间
1 小时
发表于 2012-11-13 22:05:12 | 显示全部楼层 |阅读模式
最近移植了fatfs到stm32,昨晚写进了第一个txt文件,然后就睡觉了,以为移植差不多了,今晚试了一下,发现不好用了,
res = f_open(&file, "text.txt", FA_OPEN_ALWAYS  | FA_READ | FA_WRITE);  但是复位两次就可以用了,跟踪发现的确是正好两次;
查网上有人说把MISO改为上拉,我试了下没有效果,决定自己跟踪找错误;
跟踪发现 f_open res返回1,对应FR_DISK_ERR 底层驱动错误
继续跟踪发现是f_open调用的chk_mounted的这一句fmt = check_fs(fs, bsect);检查文件系统错误;
继续跟踪发现 check_fs里的第一句if (disk_read(fs->drv, fs->win, sect, 1) != RES_OK) return 3;直接错误返回3;
继续跟踪disk_read发现是读扇区函数res = MSD_ReadSingleBlock(sector, buff); 返回res=1
继续跟踪MSD_ReadSingleBlock发现是
.......................................
............................
r1 = _send_command(CMD17, sector, 0);//独一块命令
if(r1 != 0x00)//r1!=0x00,则接收命令错误
{
return 1;//返回写块错误
}
// Start read and return the result
r1 = _read_buffer(buffer, MSD_BLOCKSIZE, RELEASE);//读MSD_BLOCKSIZE(512)个字节数据到buffer,读完后release
.................................
............................................
就是读数据时候错误返回1;
而当我想跟踪_read_buffer的时候发现只要跟踪进去,就不会返回错误1,正确的返回0,很是头大,然后仔细想一想,在r1 = _read_buffer这里设置断点跟踪就没错误,应该是和这里的时序有关,因为调试和实际运行直接时间的差别;
然后看了下_send_command(CMD17, sector, 0)时序图



断点设置的是画红圈的那里,说明延长这个时间,问题就会解决;
_read_buffer里是通过以下一段延时的
.......................................
............................
for(retry=0; retry<2000; retry++)
{
r1 = _spi_read_write(DUMMY_BYTE);
if(r1 == 0xFE)//成功
{
retry = 0;//成功标志
break;
}
}

// Timeout return超时
if(retry == 2000)
{
_card_disable();//关片选
return 1;//返回超时错误
}
.......................................
............................
程序为retry自加到2000就返回r1超时错误,设置断点在 return 1;//返回超时错误 这一句,也的确会执行到这里;
于是把程序改为for(retry=0; retry<4000; retry++),错误解决了,后来跟踪发现这里复位次retry都会自加到0x855(2133),正好超出2000!

整个错误按理说应该很好查,但是由于是复位前两次,而且错误和时序有关,设置断点的位置会影响错误存在与否,所以每一次调试都要断电,上电,打开调试,设置断点,所以跟踪到这个错误非常麻烦,也用了我一晚上的时间,写下这个,希望其他人有类似的错误可以参考下。

还有不明白的地方是:

1.为什么只在复位前两次出现这个问题?
2.chk_mounted里两次调用 check_fs,也就是两次调用disk_read,同样就是两次调用_read_buffer,跟踪发现总是第二次才出现这个错误,第一次和第二次唯一的区别是第一次读的是物理0扇区,第二次读的是物理8192扇区(我的8G SDHC,逻辑0扇区在物理扇区的8192扇区),是不是因为扇区地址大,寻址时间长了?那同样读更大的扇区会不会耗时更长?






正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-11-13 22:33:48 | 显示全部楼层
回复【楼主位】lincolne:
---------------------------------
1,这个问题怀疑是你SD卡初始化不正确。参考我们的例子试试。
2,可以排除寻址时间的问题。还是从底层驱动找问题,fatfs本身是比较稳定的了。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

2

主题

15

帖子

0

精华

新手上路

积分
47
金钱
47
注册时间
2012-11-11
在线时间
1 小时
 楼主| 发表于 2012-11-13 22:55:38 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------
1.我用的就是你们的例子啊...
2.的确不是寻址的问题,试了下读更大扇区,等待时间不长...
回复 支持 反对

使用道具 举报

2

主题

15

帖子

0

精华

新手上路

积分
47
金钱
47
注册时间
2012-11-11
在线时间
1 小时
 楼主| 发表于 2012-11-13 22:57:39 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------
有没有更好的调试方法?这种顺序的跟踪,遇到时序的问题就很头疼,有没有办法直接从一次运行结果,反跟踪哪里出了错误?刚刚接触这个调试,感觉调试很有用,但是感觉我这种方法效率不高
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-11-14 10:21:46 | 显示全部楼层
回复【4楼】lincolne:
---------------------------------
参考下我们的sd卡底层驱动。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

2

主题

15

帖子

0

精华

新手上路

积分
47
金钱
47
注册时间
2012-11-11
在线时间
1 小时
 楼主| 发表于 2012-11-15 10:25:42 | 显示全部楼层
回复【5楼】正点原子:
---------------------------------
原子兄,现在有个问题是,f_write后,f_close,如果文件在电脑上我改过之后,close就会失败,如果电脑没动过的,就会成功

是f_close里的--f_sync里的--if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) 里的--r1 = _send_command(CMD24, sector, 0);这里的r1就是写完cmd24正常应该返回0x00,这里返回0xC1

为什么会出现这种情况?如果是底层驱动的问题,为什么之前初始化没问题,写了26个扇区数据也没问题,电脑未改过的文件也没问题?
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-11-15 13:47:27 | 显示全部楼层
这就不太清楚了,你电脑怎么改的?
拔了SD卡,放到电脑上改?还是直接电脑连接STM32,再改?
我没碰到过这种情况哦
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

2

主题

15

帖子

0

精华

新手上路

积分
47
金钱
47
注册时间
2012-11-11
在线时间
1 小时
 楼主| 发表于 2012-11-15 16:35:10 | 显示全部楼层
回复【7楼】正点原子:
---------------------------------
拔掉sd卡放到电脑上,随便写几个字符...
回复 支持 反对

使用道具 举报

2

主题

15

帖子

0

精华

新手上路

积分
47
金钱
47
注册时间
2012-11-11
在线时间
1 小时
 楼主| 发表于 2012-11-19 09:01:20 | 显示全部楼层
回复【7楼】正点原子:
---------------------------------
原子兄,现在是写入超过1024字节后,f_close会失败,因为大于1024字节后会调用write_multi连续写多扇区,但是跟踪发现数据已经成功写入了,只是不能close保存文件。
而把write_multi函数改成两次write_single的时候,f_close可以成功关闭保存
f_close之前disk_int重新初始化一下sd卡,可以解决这个问题

这个情况你能帮我分析下不,底层驱动和你的例程没什么区别的write_multi能成功,但是为什么能影响到f_close
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-11-19 10:06:35 | 显示全部楼层
这我也不太清楚了。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-7-18 18:26

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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