无聊中,喷喷调试中得到的经验,挣点莫元吧。
移植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天,有够无聊。公示出来也许可以减少别人的重复的无聊。
|