以前刚开始学习的时候,跟着教程一步步移植OK了,突然想回顾一下,于是发现FatFs更新了R0.14的版本,于是便尝试一下移植,总结一下我遇到的问题并怎么解决的
1.直接移植官方的参考例程的时候要注意,里面有这三个
STM324x7I_EVAL
STM324x9I_EVAL
STM3240_41_G_EVAL
当时一开始移植第三个,我的芯片是F407,搞错了, 但是单块写入读取都是OK的,于是直接开始移植FatFs,然后一直报错,怎么都不行。。心态爆炸,然后耐心一步步找,最后发现了这个问题,还有一个问题,SDIO还需移植其DMA中断函数,如果不移植也不会报错,因在启动文件有弱定义,难以发现问题。
总结:移植要看好对应芯片才行
2.字节对齐问题,最好这个函数先封装好,放在sdio的C文件里,先测试好,不然像我这样字节上手写到FatFs的WRITE和READ底层驱动函数,怎么写怎么错,要一步步搭建才对。。我分享一下我的处理函数
/**
* @brief FatFs读函数,主要用于对齐地址
* @param buf 保存的BUF
* @param sector 扇区号
* @param BlockSize 块大小
* @param NumBlock 要读的块数量
* @retval None
*/
__align(4) uint8_t RX_BUFF[512];
SD_Error FatfsRead_Disk(uint8_t* buf,uint32_t sector,uint16_t BlockSize,uint32_t NumBlock){
SD_Error sta;
uint16_t cnt;
uint32_t lsector=sector;
lsector*=512; //记得,大容量SD卡最小单位是512字节,因此扇区要( ×512 ),或者是( <<9 )也可以
if(((uint32_t)buf%4)!=0)
{
for(cnt=0;cnt<NumBlock;cnt++)
{
sta = SD_ReadBlock(RX_BUFF,lsector+512*cnt,BlockSize);
if(sta!=SD_OK)
{
printf("SD_ReadBlock fail");
break;
}
sta = SD_WaitReadOperation();
if (sta != SD_OK)
{
printf("SD_WaitReadOperation Status = %d\r\n",sta);
return SD_ERROR;
}
while(SD_GetStatus() != SD_TRANSFER_OK);
memcpy(buf,RX_BUFF,BlockSize);
buf+=512;
}
}
else
{
SD_ReadMultiBlocks(buf,lsector,BlockSize,NumBlock);
sta = SD_WaitReadOperation();
if(sta!=SD_OK)
{
printf("SD_WaitReadOperation fail \r\n");
return SD_ERROR;
}
while(SD_GetStatus()!=SD_TRANSFER_OK);
}
return sta;
}
SD_WaitReadOperation()和 SD_GetStatus()在读单块和多块都一定要加,不加会出错。。血的教训,因为ST文件讲了一定要加
/**
* @brief FatFs写函数,字节对齐,和读基本一样思路
* @param buf 要写入的BUF
* @param sector 扇区号
* @param BlockSize 块大小
* @param NumBlock 要写的块数量
* @retval None
*/
SD_Error FatfsWrite_Disk(uint8_t* buf,uint32_t sector,uint16_t BlockSize,uint32_t NumBlock){
SD_Error sta;
uint16_t cnt;
uint32_t lsector=sector;
lsector*=512;
if(((uint32_t)buf%4)!=0)
{
for(cnt=0;cnt<NumBlock;cnt++)
{
memcpy(RX_BUFF,buf,BlockSize);
sta = SD_WriteBlock(RX_BUFF,lsector+512*cnt,BlockSize);
if(sta!=SD_OK)
{
printf("SD_WriteBlock fail");
break;
}
sta = SD_WaitWriteOperation();
if (sta != SD_OK)
{
printf("SD_WaitWriteOperation Status = %d\r\n",sta);
return SD_ERROR;
}
while(SD_GetStatus() != SD_TRANSFER_OK);
buf+=512;
}
}
else
{
SD_WriteMultiBlocks(buf,lsector,BlockSize,NumBlock);
sta = SD_WaitWriteOperation();
if(sta!=SD_OK)
{
printf("SD_WaitWROpera fail \r\n");
return SD_ERROR;
}
while(SD_GetStatus()!=SD_TRANSFER_OK);
}
return sta;
}
当所有多块读写,单块读写都测试OK了,为了成功你可以先注释代码,所有分支都测一下是否合符预想。
3.然后一直卡F_MOUNT()函数,一直返回1(FR_DISK_ERR),查了很多资料,最后没办法,DEBUG看看,一步步找,发现到了disk_initialize()函数里面,switch (pdrv)的值不对,没有执行下面SD卡分支的初始化,所以读写失败了,后来把DEV_SD_CARD从 1 改成了 0,然后就成功了。。暂时不知道是什么情况,难道都是从0开始,按顺序初始化的吗
4.最后打开,写入也OK了,符合预期,然后发现f_read()函数,返回0(OK),但是br的返回值为0,我就纳闷了,然后又开始DEBUG大法,发现这个函数
remain = fp->obj.objsize - fp->fptr;
for ( ; btr; /* Repeat until btr bytes read */
btr -= rcnt, *br += rcnt, rbuff += rcnt, fp->fptr += rcnt) {
if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */
这里的remain为0,这两个值都为0xA,不执行下面的for循环了。查了一下这个结构体注释为
SIZE_t fptr; /* File read/write pointer (Zeroed on file open) */