查看: 936|回复: 0
打印 上一主题 下一主题

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

[复制链接]
跳转到指定楼层
沙发
发表于 2016-4-12 19:34:18 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
无聊中,喷喷调试中得到的经验,挣点莫元吧。
移植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天,有够无聊。公示出来也许可以减少别人的重复的无聊。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入因仑

本版积分规则

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