为什么FatFs的f_lseek函数执行时间从会几us到几秒钟增加,见图
我在测试播放一个2GB的无压缩BMP编码的avi视频文件,分辨率320*240 (主芯片STM32F407)测试发现刚开始播放的速度能到7fps(主要播放速度受读SD速度限制,一张320*240,24位的图片就225KB了),
可是速度会慢慢的下降,慢慢的降到零点几fps
调试跟踪发现是卡在了f_lseek 文件偏移函数中
复位后,刚开始f_lseek用时才几us,随着播放,几秒钟后就升到了几百个ms,在过多一会甚至是用时1秒多..
刚刚移植了2015年9月份的 R0.11版本,也是如此,不知道大家有没有遇见过这样的问题
见图:(这个是f_lseek函数用时537ms的图片,大概播放了20多秒就降到了500多毫秒了)
测试过,SD卡的读速度一直都拨动不大,问题在于f_lseek 那你跟一下这个f_lseek吧,看看瓶颈到底在哪里 myxiaonia 发表于 2015-9-2 14:14
那你跟一下这个f_lseek吧,看看瓶颈到底在哪里
是的,就是卡在这里,一直循环很久,但刚开始又不会
while (ofs > bcs) { /* Cluster following loop */
clst = get_fat(fp->fs, clst); /* Follow cluster chain if not in write mode */
if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
if (clst <= 1 || clst >= fp->fs->n_fatent) ABORT(fp->fs, FR_INT_ERR);
fp->clust = clst;
fp->fptr += bcs;
ofs -= bcs;
} 在同个已cache的sector中,当然很快。
如果新的位置还要读磁盘,那可想而知了。
所以最好应用这块好好优化,即使用seek也不要乱跳。 aozima 发表于 2015-9-2 14:54
在同个已cache的sector中,当然很快。
如果新的位置还要读磁盘,那可想而知了。
按理说fat缓存时会缓存至少512字节的fat表区域,如果视频文件是连续存放的话也会有不少扇区的连续的,这个fat缓存就会连续命中,不可能出现一直性能下降的问题
而是像周期波一样 myxiaonia 发表于 2015-9-2 15:03
按理说fat缓存时会缓存至少512字节的fat表区域,如果视频文件是连续存放的话也会有不少扇区的连续的,这 ...
有道理
有个细节忘记说了
实际上,在一个循环中,我用了两次f_lseek,
一次是找到视频流头后用了f_lseek,因为有音频数据,要跳过音频数据。也就是说不使用跳过的这些音频数据。这些数据大约4KB,卡的就只有这一次,另一次永远也不会卡哦
另一次是用于循环读取视频流中一帧的图片数据(225KB),我一次读取10KB。这次调用f_lseek没有卡过,很流畅
开启FATFS的FAST_SEEK宏,open文件时创建 CLMT ,类似将FAT表压缩储存,以后seek就不用再去读FAT表了
/* Using fast seek feature */
DWORD clmt; /* Cluster link map table buffer */
res = f_open(fp, fname, FA_READ | FA_WRITE); /* Open a file */
res = f_lseek(fp, ofs1); /* This is normal seek (cltbl is nulled on file open) */
fp->cltbl = clmt; /* Enable fast seek feature (cltbl != NULL) */
clmt = SZ_TBL; /* Set table size */
res = f_lseek(fp, CREATE_LINKMAP); /* Create CLMT */
...
res = f_lseek(fp, ofs2); /* This is fast seek */ zzm24 发表于 2015-9-2 16:44
开启FATFS的FAST_SEEK宏,open文件时创建 CLMT ,类似将FAT表压缩储存,以后seek就不用再去读FAT表了
/* U ...
真的非常感谢你
问题总算解决了,播放视频一下子快起来了
而且这对于告诉读写大文件非常有利,现在f_lseek函数执行时间总保持在0.6ms左右,太兴奋了
相信很多人都不知道这个,学习了 0.11版里是 #define _USE_FASTSEEK 1 我以前也碰到f_lseek的定位大文件的问题, 后来多加了一个f_lseek函数, 加入延时10us, 然后没问题了, 原来是FAST_SEEK宏的原因啊. lxl_lxl 发表于 2015-9-2 17:26
真的非常感谢你
问题总算解决了,播放视频一下子快起来了
你好,我用fastseek无法多次写入了,能不能把fastseek的那段代码分享一下 这就解决了 zhongsandaoren 发表于 2018-7-23 17:14
这就解决了
你好,我用fastseek无法多次写入了,你知道具体是如何解决的吗 zzm24 发表于 2015-9-2 16:44
开启FATFS的FAST_SEEK宏,open文件时创建 CLMT ,类似将FAT表压缩储存,以后seek就不用再去读FAT表了
/* U ...
15年的贴子,被我找到了,并且帮助我解决了问题,非常感谢!
/* Using fast seek function */
DWORD clmt; /* Cluster link map table buffer */
res = f_open(fp, fname, FA_READ | FA_WRITE); /* Open a file */
res = f_lseek(fp, ofs1); /* This is normal seek (cltbl is nulled on file open) */
fp->cltbl = clmt; /* Enable fast seek function (cltbl != NULL) */
clmt = SZ_TBL; /* Set table size */
res = f_lseek(fp, CREATE_LINKMAP); /* Create CLMT */
...
res = f_lseek(fp, ofs2); /* This is fast seek */
======================分割线:下面是我实际使用时的解决办法==============================
#define SZ_TBL20
static DataWrite(void)//周期执行函数,周期往文件里写数据
{
static DWORD clmt; /* Cluster link map table buffer */
res = f_open(fp, fname, FA_READ | FA_WRITE); /* Open a file */
if(clmt == 0x00)
{
res = f_lseek(fp, f_sizeof(fp)); /* This is normal seek (cltbl is nulled on file open) */
faddata.cltbl = clmt;
clmt = SZ_TBL;
res = f_lseek(fp,CREATE_LINKMAP);
}
else fp->cltbl = clmt;//每次f_open后,fp->cltbl会变成NULL,所以要把第clmt的地址再次赋值给cltbl
res = f_seek(fp,f_size(fp));
res = f_write(fp,WriteDataBuf,strlen(WriteDataBuf),&bw);
res = f_close(fp);
}
以前没注意,学习了 学习了,谢谢
页:
[1]