搜索
bottom↓
回复: 43

立此存照:SDIO+fatfs的一些细节问题

  [复制链接]

出0入0汤圆

发表于 2012-7-26 15:14:29 | 显示全部楼层 |阅读模式
无聊中,喷喷调试中得到的经验,挣点莫元吧。
移植fatfs 0.09,stm32f103vet6, sdio 4bit模式,fwlib还是用2.03,移植很顺利,diskio.c写了几句就能跑,f_mount,读写通过。
读出640x480x16bit bitmap文件显示,出现问题,f_read()每次只能读512byte,超出就出现读数据错:每次读一行1280Byte,出现一条竖线;分成3次读就没问题。虽然也能用,不免有点太监的感觉。
跟踪问题,f_read() --> SD_ReadBlock()-->DMA_RxConfiguration(),猜到这是DMA 32Bit的问题:SDIO的FIFO是32Bit的,DMA接收地址要u32 *, 最低2Bit为0; 读的时候这个基地址由fatfs的f_read()、SD_ReadBlock()分配,fatfs中保存1-Sector(512Bytes)缓存,每次f_read()时,主程序传来readbuffer, 先将sector buffer中“剩余”的bytes用mem_cpy送给readbuffer, 不够再启动SD_ReadBlock()读; 又分成两种情况:要读的不足1Sector,以fatfs的sector buffer作为DMA接收区,再mem_cpy给readbuffer; 要读的是整数sector,就直接以readbuffer作为DMA接收区。
问题就出在这第二种情况:这时的read buffer即使初始是4Byte对齐的(u32 *),加上sector buffer中“剩余”Bytes的偏移之后,也不会是确保4Byte对齐的了。具体到bitmap文件读:先读文件头70Byte,fatfs读512Byte,剩余442Byte;读一行1280Byte,送m_FileIo_Buf[]作为接收区,2KByte; fatfs先将442Byte送给m_FileIo_Buf,启动SD_ReadBlock(), 从m_FileIo_Buf+442位置接收DMA...出错了,地址A1不是0!
这个问题谁都没错,fatfs和sdio都是按自己正确的方式工作。开发板们给出的例程,f_read()读512内Byte,也不会错...
想一次读超过512的话,解决的办法:
定义:
u8 m_FileIo_Buf[2048]  __attribute__((aligned(4)));               //接收缓冲区
#define M_FileAlignAdj(pFile)       (4 - (512 - ((uint32_t)((pFile)->fptr) & 0x01FF)) & 0x0003)
程序中:
     u8* ptr;
       //读文件
        ptr = m_FileIo_Buf;
        ptr += M_FileAlignAdj(bmpfile);
        res = f_read(bmpfile, ptr, bytes_per_row, &bytenum);
       //从ptr处读数据....
原理很简单:每次读的接收指针ptr在m_FileIo_Buf[]的前4Byte之间移动,经过f_read()之后,DMA接收SD Sector数据时一定是(u32 *)地址。
这个小小的问题折腾了3天,有够无聊。公示出来也许可以减少别人的重复的无聊。


出0入0汤圆

发表于 2012-7-26 15:45:40 | 显示全部楼层
很好,谢谢。

出0入0汤圆

发表于 2012-7-27 09:32:20 | 显示全部楼层
MARK了谢谢楼主

出0入0汤圆

发表于 2012-8-17 11:08:37 | 显示全部楼层
表示同样遇到此问题,谢谢了!!!
我是读800*480 bmp出问题。

出0入0汤圆

发表于 2012-8-21 00:16:39 | 显示全部楼层
本帖最后由 nicotinecys 于 2012-8-21 00:36 编辑

哥哥,你太强了!!已经看懂你的意思!谢谢

出0入0汤圆

发表于 2012-8-21 00:25:57 | 显示全部楼层
楼主分享心得,很好,谢谢~

出0入0汤圆

发表于 2012-8-22 20:46:02 | 显示全部楼层
来了 就留个记号

出0入0汤圆

发表于 2013-3-9 22:22:41 | 显示全部楼层
留个记号, 以后可能用得上!

出0入0汤圆

发表于 2013-3-10 10:44:52 | 显示全部楼层
先记下,以后注意

出0入0汤圆

发表于 2013-3-10 11:11:45 | 显示全部楼层
做个记号啊,说不定哪天我也弄文件系统呢

出0入0汤圆

发表于 2013-4-24 20:01:22 | 显示全部楼层
地址A1是那里来的?这里不太理解

出0入0汤圆

 楼主| 发表于 2013-4-27 15:07:11 | 显示全部楼层
Sean_mcu 发表于 2013-4-24 20:01
地址A1是那里来的?这里不太理解

系统总线地址[A31..A1A0]

出0入0汤圆

发表于 2013-5-4 20:36:54 | 显示全部楼层
chunxx 发表于 2013-4-27 15:07
系统总线地址[A31..A1A0]

我发现我写入文件时也遇到了,类似的情况!
那要怎么改呢?总不能在fatfs的512buffer下功夫吧!!

出0入0汤圆

发表于 2013-5-4 21:17:16 | 显示全部楼层
有个大神解决了...但是我想不起来大神的ID了...再次表达敬意...

解决方法如下:
  1.     SDDMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
  2.     SDDMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
复制代码

出0入0汤圆

发表于 2013-5-5 15:02:45 | 显示全部楼层
adce 发表于 2013-5-4 21:17
有个大神解决了...但是我想不起来大神的ID了...再次表达敬意...

解决方法如下: ...

这两行代码是给我看的吗?
我的实际情况是:每次写入u8【650*2】的数组是行的,但是循环到第308次是就出错了。
我也不知道出错在哪!每次写f_write返回都是FR_OK。
后来在电脑上看sd的文件发现大小是0.
为什么总的文件写入量会被限制在389.7kb呢?
求请教!!感激不尽~

出0入0汤圆

发表于 2013-5-5 15:38:27 | 显示全部楼层
Sean_mcu 发表于 2013-5-5 15:02
这两行代码是给我看的吗?
我的实际情况是:每次写入u8【650*2】的数组是行的,但是循环到第308次是就出 ...

这个是解决楼主问题的...

您的这个问题原因不明...

但是我提供的那两行一定是要改的...
目前没发现用DMA的例程是对的...都需要这么改...包括官方例程...

您可以贴一下代码....感觉您这个问题应该是某些地方大意了造成的...

出0入0汤圆

发表于 2013-5-5 19:43:16 | 显示全部楼层
强悍的人。。。

出0入0汤圆

发表于 2013-5-5 21:13:54 | 显示全部楼层
顶帖,备用。

出0入0汤圆

发表于 2013-5-5 22:54:17 | 显示全部楼层
学习了...感谢楼主分享....

出0入0汤圆

发表于 2013-5-5 23:10:58 | 显示全部楼层
呵呵,刚好今天解决了一个问题又碰到这个问题,还没想到解决办法就看到这个了,大爱楼主!

出0入0汤圆

发表于 2013-8-14 19:21:54 | 显示全部楼层
向楼主学习,帮助我解决了图片的条纹问题,也将我的修改贴出来:
u8 data_buf_offset;//数组偏移量
u8 * p;//字符指针
u8 buffer[2048];//字符数组,存放读取的数据,分辨率太大的时候要随之修改
FIL fsrc;
u8 data_file_w;//图片的行像素数目,*3是因为图片是24真彩色
主要的语句为:
       data_buf_offset = (4 - (512 - ((uint32_t)(fsrc.fptr))&0x01ff)&0x03);
        p = buffer;
        p += data_buf_offset;
        f_read(&fsrc, p, data_file_w*3, &br);

出0入0汤圆

发表于 2013-8-16 17:21:53 | 显示全部楼层

出0入0汤圆

发表于 2013-8-29 22:55:15 | 显示全部楼层
楼主真有钻研精神, 佩服
这个问题我折腾了好几天,太感谢了

出0入0汤圆

发表于 2013-8-30 17:19:10 | 显示全部楼层
mark了,谢谢lz

出0入0汤圆

发表于 2013-10-25 18:26:06 | 显示全部楼层
太好了,正好解决问题

出0入0汤圆

发表于 2013-10-28 13:11:49 | 显示全部楼层
MARK .. 留着备用

出0入0汤圆

发表于 2013-11-2 10:41:34 | 显示全部楼层
还没来得及看,先mark

出0入0汤圆

发表于 2013-12-15 00:23:43 | 显示全部楼层
adce 发表于 2013-5-4 21:17
有个大神解决了...但是我想不起来大神的ID了...再次表达敬意...

解决方法如下: ...

这个可以解决读错数据的问题?我的是当我在程序里面定义了一个不相关的数组以后,读回来的数据前两个字节就错了,把数组取消就没问题了

出0入0汤圆

发表于 2013-12-15 00:28:47 | 显示全部楼层
大概明白了,但还是有些不明白的地方,还请楼主再解释下,

出0入0汤圆

发表于 2013-12-15 00:30:08 | 显示全部楼层
xiaofei_515 发表于 2013-8-14 19:21
向楼主学习,帮助我解决了图片的条纹问题,也将我的修改贴出来:
u8 data_buf_offset;//数组偏移量
u8 * p; ...

可以给解释下吗,有些看不明白

出0入0汤圆

发表于 2013-12-21 11:04:04 | 显示全部楼层
楼主这样岂不是会导致收到的数据并不是从m_FileIo_Buf[]的第一个字节开始存放?

出0入54汤圆

发表于 2014-3-15 17:43:44 | 显示全部楼层
adce 发表于 2013-5-4 21:17
有个大神解决了...但是我想不起来大神的ID了...再次表达敬意...

解决方法如下: ...

顶一下,使用这个方法解决了。
SDIO定义成4字节
memory定义成BYTE

出0入0汤圆

发表于 2014-4-22 10:00:06 | 显示全部楼层
感谢楼主,终于调通了

出0入0汤圆

发表于 2014-5-15 11:20:43 | 显示全部楼层
论坛就该有这些去搞底层解决问题得人,虽然我的FAT没遇到这个问题,不过先看明白了,指不定以后什么时候用得到。

出0入0汤圆

发表于 2014-5-15 11:41:56 来自手机 | 显示全部楼层
也在搞FATFS ,想问问f_opendir出现FR_NOT_ENABLE是什么意思?

出0入0汤圆

发表于 2014-9-22 16:57:26 | 显示全部楼层
adce 发表于 2013-5-4 21:17
有个大神解决了...但是我想不起来大神的ID了...再次表达敬意...

解决方法如下: ...

这样会不会影响速度呢?

出0入0汤圆

发表于 2014-9-22 17:51:38 | 显示全部楼层
先收着,准备搞FATFS

出0入10汤圆

发表于 2014-9-29 19:05:39 | 显示全部楼层
nicotinecys 发表于 2012-8-21 00:16
哥哥,你太强了!!已经看懂你的意思!谢谢

大家能否帮忙解释下,看不懂啊!

出0入0汤圆

发表于 2015-5-3 20:41:48 | 显示全部楼层
同样遇到此问题,虽然楼主那个地址偏移的宏不甚明白,但仍启发了我正确的思路,谢谢!

出0入0汤圆

发表于 2015-5-5 09:26:43 | 显示全部楼层
楼主好人

出0入0汤圆

发表于 2015-11-11 09:41:01 | 显示全部楼层
mark mark。。

出0入0汤圆

发表于 2015-11-12 23:26:42 | 显示全部楼层
标记备用

出0入0汤圆

发表于 2015-11-18 16:25:41 | 显示全部楼层
厲害的樓主,佩服!!!

出0入0汤圆

发表于 2015-11-18 17:32:39 | 显示全部楼层
收藏了~~~~~~~~~~~~
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-3 04:00

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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