移植FatFs总结

以前刚开始学习的时候,跟着教程一步步移植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) */

恍然大悟,这里是一个光标指针,因测试代码是先写入,然后光标移动到最后,这时候读肯定是没有了。于是最后注释了f_write()函数。测试全部OK!哈哈,开心,搞了1个星期,下一步真被搞一下SD卡的IAP更新

网上查不到资料,只能自己多试试了,希望我的移植总结能给你带来思路,多DEBUG追踪,代码一步步测试,OK了才进行下一步,好了,继续研究研究怎么加入FreeRTOS。。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值