首页 > 代码库 > stm32—FatFs移植spi_flash(报错FR_NO_FILESYSTEM)

stm32—FatFs移植spi_flash(报错FR_NO_FILESYSTEM)

        SD卡的FatFs文件系统已经满大街了,可以参考的资源也有很多。

        移植FatFs文件系统主要内容在于“diskio.c”,“ffconf.h”,一个是用于定义底层接口,一个用于定义FatFs配置,百度或者google都能找得到说明,就不详细说明了。

        碰到的主要问题就是f_mkfs()函数过后,Fat系统没有刷新成功,于是f_open()返回(FR_NO_FLESYSTEM),文件系统没有刷新成功。

        开始查ff.c文件 ,进入f_mkfs:

FRESULT f_mkfs (
	BYTE drv,		/* Logical drive number */
	BYTE sfd,		/* Partitioning rule 0:FDISK, 1:SFD */
	UINT au			/* Allocation unit size [bytes] */
)
{
	static const WORD vst[] = { 1024,   512,  256,  128,   64,    32,   16,    8,    4,    2,   0};
	static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512};
	BYTE fmt, md, sys, *tbl, pdrv, part;
	DWORD n_clst, vs, n, wsect;
	UINT i;
	DWORD b_vol, b_fat, b_dir, b_data;	/* LBA */
	DWORD n_vol, n_rsv, n_fat, n_dir;	/* Size */
	FATFS *fs;
	DSTATUS stat;


	/* Check mounted drive and clear work area */
	if (drv >= _VOLUMES) return FR_INVALID_DRIVE;
	if (sfd > 1) return FR_INVALID_PARAMETER;
	if (au & (au - 1)) return FR_INVALID_PARAMETER;
	fs = FatFs[drv];
	if (!fs) return FR_NOT_ENABLED;
	fs->fs_type = 0;
	pdrv = LD2PD(drv);	/* Physical drive */
	part = LD2PT(drv);	/* Partition (0:auto detect, 1-4:get from partition table)*/

	/* Get disk statics */
	stat = disk_initialize(pdrv);
	if (stat & STA_NOINIT) return FR_NOT_READY;
	if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
#if _MAX_SS != 512					/* Get disk sector size */
	if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS)
		return FR_DISK_ERR;
#endif
	if (_MULTI_PARTITION && part) {
		/* Get partition information from partition table in the MBR */
		if (disk_read(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR;
		if (LD_WORD(fs->win+BS_55AA) != 0xAA55) return FR_MKFS_ABORTED;
		tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE];
		if (!tbl[4]) return FR_MKFS_ABORTED;	/* No partition? */
		b_vol = LD_DWORD(tbl+8);	/* Volume start sector */
		n_vol = LD_DWORD(tbl+12);	/* Volume size */
	} else {
		/* Create a partition in this function */
		if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128)
			return FR_DISK_ERR;
		b_vol = (sfd) ? 0 : 63;		/* Volume start sector */
		n_vol -= b_vol;				/* Volume size */
	}

	if (!au) {				/* AU auto selection */
		vs = n_vol / (2000 / (SS(fs) / 512));
		for (i = 0; vs < vst[i]; i++) ;
		au = cst[i];
	}
	au /= SS(fs);		/* Number of sectors per cluster */
	if (au == 0) au = 1;
	if (au > 128) au = 128;

	/* Pre-compute number of clusters and FAT sub-type */
	n_clst = n_vol / au;
	fmt = FS_FAT12;
	if (n_clst >= MIN_FAT16) fmt = FS_FAT16;
	if (n_clst >= MIN_FAT32) fmt = FS_FAT32;

	/* Determine offset and size of FAT structure */
	if (fmt == FS_FAT32) {
		n_fat = ((n_clst * 4) + 8 + SS(fs) - 1) / SS(fs);
		n_rsv = 32;
		n_dir = 0;
	} else {
		n_fat = (fmt == FS_FAT12) ? (n_clst * 3 + 1) / 2 + 3 : (n_clst * 2) + 4;
		n_fat = (n_fat + SS(fs) - 1) / SS(fs);
		n_rsv = 1;
		n_dir = (DWORD)N_ROOTDIR * SZ_DIR / SS(fs);
	}
	b_fat = b_vol + n_rsv;				/* FAT area start sector */
	b_dir = b_fat + n_fat * N_FATS;		/* Directory area start sector */
	b_data = http://www.mamicode.com/b_dir + n_dir;				/* Data area start sector */>在线仿真,发现函数在disk_write处存在问题,于是开始改写该底层函数
/*************************************************************************************** 名    称: disk_write* 功    能: Write Sector(s)  * 参    数: drv:表示需要读扇区的磁盘对象*<span style="white-space:pre">			</span> BYTE drv: Physical drive nmuber (0..) *<span style="white-space:pre">		</span> BYTE *buff: Data buffer to store read data *<span style="white-space:pre">	</span> DWORD sector: Sector address (LBA) *<span style="white-space:pre">	</span>   BYTE count: Number of sectors to read (1..128) * 调用方式:disk_initialize(0,buff,0,1);* 返 回 值:<span style="white-space:pre">	</span>状态标识0:表示成功***************************************************************************************/void flash_page_write_si(uint32_t sector,uint8_t *data){<span style="white-space:pre">	</span>uint16_t i;<span style="white-space:pre">	</span>  SPI_FLASH_WriteEnable();  /* Select the FLASH: Chip Select low */  SPI_FLASH_CS_LOW();  /* Send "Write to Memory " instruction */  SPI_FLASH_SendByte(0x02);  /* Send WriteAddr high nibble address byte to write to */  SPI_FLASH_SendByte((sector & 0xFF0000) >> 16);  /* Send WriteAddr medium nibble address byte to write to */  SPI_FLASH_SendByte((sector & 0xFF00) >> 8);  /* Send WriteAddr low nibble address byte to write to */  SPI_FLASH_SendByte(sector & 0xFF);<span style="white-space:pre">	</span>for (i = 0; i < FLASH_SECTOR_SIZE; i++)<span style="white-space:pre">	</span>{<span style="white-space:pre">		</span>SPI_FLASH_SendByte(*data++);<span style="white-space:pre">	</span>}  SPI_FLASH_CS_HIGH();  /* Wait the end of Flash writing */  SPI_FLASH_WaitForWriteEnd();}DSTATUS disk_write (BYTE drv,const BYTE *buff,<span style="white-space:pre">	</span>DWORD sector,<span style="white-space:pre">	</span>BYTE count){<span style="white-space:pre">	</span><span style="white-space:pre">	</span>flash_page_write_si(sector,(uint8_t *)buff);<span style="white-space:pre">	</span>return RES_OK;}

disk_write改写完成,是对内存块进行写操作。这样子flash的初始化应该算是完成了。再次烧录程序,报错相同。

进入f_open函数,发现错误返回在chk_mounted(),进入该函数,发现check_fs()才是罪魁祸首,

	fmt = check_fs(fs, bsect = 0);		/* Load sector 0 and check if it is an FAT-VBR (in SFD) */
	if (LD2PT(vol) && !fmt) fmt = 1;	/* Force non-SFD if the volume is forced partition */
	if (fmt == 1) {						/* Not an FAT-VBR, the physical drive can be partitioned */
		/* Check the partition listed in the partition table */
		pi = LD2PT(vol);
		if (pi) pi--;
		tbl = &fs->win[MBR_Table + pi * SZ_PTE];/* Partition table */
		if (tbl[4]) {						/* Is the partition existing? */
			bsect = LD_DWORD(&tbl[8]);		/* Partition offset in LBA */
			fmt = check_fs(fs, bsect);		/* Check the partition */
		}
	}
	if (fmt == 3) return FR_DISK_ERR;
	if (fmt) return FR_NO_FILESYSTEM;		/* No FAT volume is found */
研究了很久,还是找不到问题所在,于是请教了一个大神,说可能是flash大小问题,我使用的是2M大小,大神说fat系统的管理所占用的内存就非常大,要不就自己做小个小型的文件系统来实现这个功能。好吧,受教了。

stm32—FatFs移植spi_flash(报错FR_NO_FILESYSTEM)