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 = b_dir + n_dir;				/* Data area start sector */
	if (n_vol < b_data + au - b_vol) return FR_MKFS_ABORTED;	/* Too small volume */

	/* Align data start sector to erase block boundary (for flash memory media) */
	if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1;
	n = (b_data + n - 1) & ~(n - 1);	/* Next nearest erase block from current data start */
	n = (n - b_data) / N_FATS;
	if (fmt == FS_FAT32) {		/* FAT32: Move FAT offset */
		n_rsv += n;
		b_fat += n;
	} else {					/* FAT12/16: Expand FAT size */
		n_fat += n;
	}

	/* Determine number of clusters and final check of validity of the FAT sub-type */
	n_clst = (n_vol - n_rsv - n_fat * N_FATS - n_dir) / au;
	if (   (fmt == FS_FAT16 && n_clst < MIN_FAT16)
		|| (fmt == FS_FAT32 && n_clst < MIN_FAT32))
		return FR_MKFS_ABORTED;

	switch (fmt) {	/* Determine system ID for partition table */
	case FS_FAT12:	sys = 0x01; break;
	case FS_FAT16:	sys = (n_vol < 0x10000) ? 0x04 : 0x06; break;
	default: 		sys = 0x0C;
	}

	if (_MULTI_PARTITION && part) {
		/* Update system ID in the partition table */
		tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE];
		tbl[4] = sys;
		if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR;
		md = 0xF8;
	} else {
		if (sfd) {	/* No partition table (SFD) */
			md = 0xF0;
		} else {	/* Create partition table (FDISK) */
			mem_set(fs->win, 0, SS(fs));
			tbl = fs->win+MBR_Table;	/* Create partition table for single partition in the drive */
			tbl[1] = 1;						/* Partition start head */
			tbl[2] = 1;						/* Partition start sector */
			tbl[3] = 0;						/* Partition start cylinder */
			tbl[4] = sys;					/* System type */
			tbl[5] = 254;					/* Partition end head */
			n = (b_vol + n_vol) / 63 / 255;
			tbl[6] = (BYTE)((n >> 2) | 63);	/* Partition end sector */
			tbl[7] = (BYTE)n;				/* End cylinder */
			ST_DWORD(tbl+8, 63);			/* Partition start in LBA */
			ST_DWORD(tbl+12, n_vol);		/* Partition size in LBA */
			ST_WORD(fs->win+BS_55AA, 0xAA55);	/* MBR signature */
			if (disk_write(pdrv, fs->win, 0, 1) != RES_OK)	/* Write it to the MBR sector */
				return FR_DISK_ERR;
			md = 0xF8;
		}
	}

	/* Create BPB in the VBR */
	tbl = fs->win;							/* Clear sector */
	mem_set(tbl, 0, SS(fs));
	mem_cpy(tbl, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code, OEM name */
	i = SS(fs);								/* Sector size */
	ST_WORD(tbl+BPB_BytsPerSec, i);
	tbl[BPB_SecPerClus] = (BYTE)au;			/* Sectors per cluster */
	ST_WORD(tbl+BPB_RsvdSecCnt, n_rsv);		/* Reserved sectors */
	tbl[BPB_NumFATs] = N_FATS;				/* Number of FATs */
	i = (fmt == FS_FAT32) ? 0 : N_ROOTDIR;	/* Number of rootdir entries */
	ST_WORD(tbl+BPB_RootEntCnt, i);
	if (n_vol < 0x10000) {					/* Number of total sectors */
		ST_WORD(tbl+BPB_TotSec16, n_vol);
	} else {
		ST_DWORD(tbl+BPB_TotSec32, n_vol);
	}
	tbl[BPB_Media] = md;					/* Media descriptor */
	ST_WORD(tbl+BPB_SecPerTrk, 63);			/* Number of sectors per track */
	ST_WORD(tbl+BPB_NumHeads, 255);			/* Number of heads */
	ST_DWORD(tbl+BPB_HiddSec, b_vol);		/* Hidden sectors */
	n = get_fattime();						/* Use current time as VSN */
	if (fmt == FS_FAT32) {
		ST_DWORD(tbl+BS_VolID32, n);		/* VSN */
		ST_DWORD(tbl+BPB_FATSz32, n_fat);	/* Number of sectors per FAT */
		ST_DWORD(tbl+BPB_RootClus, 2);		/* Root directory start cluster (2) */
		ST_WORD(tbl+BPB_FSInfo, 1);			/* FSInfo record offset (VBR+1) */
		ST_WORD(tbl+BPB_BkBootSec, 6);		/* Backup boot record offset (VBR+6) */
		tbl[BS_DrvNum32] = 0x80;			/* Drive number */
		tbl[BS_BootSig32] = 0x29;			/* Extended boot signature */
		mem_cpy(tbl+BS_VolLab32, "NO NAME    " "FAT32   ", 19);	/* Volume label, FAT signature */
	} else {
		ST_DWORD(tbl+BS_VolID, n);			/* VSN */
		ST_WORD(tbl+BPB_FATSz16, n_fat);	/* Number of sectors per FAT */
		tbl[BS_DrvNum] = 0x80;				/* Drive number */
		tbl[BS_BootSig] = 0x29;				/* Extended boot signature */
		mem_cpy(tbl+BS_VolLab, "NO NAME    " "FAT     ", 19);	/* Volume label, FAT signature */
	}
	ST_WORD(tbl+BS_55AA, 0xAA55);			/* Signature (Offset is fixed here regardless of sector size) */
	if (disk_write(pdrv, tbl, b_vol, 1) != RES_OK)	/* Write it to the VBR sector */
		return FR_DISK_ERR;
	if (fmt == FS_FAT32)							/* Write backup VBR if needed (VBR+6) */
		disk_write(pdrv, tbl, b_vol + 6, 1);

	/* Initialize FAT area */
	wsect = b_fat;
	for (i = 0; i < N_FATS; i++) {		/* Initialize each FAT copy */
		mem_set(tbl, 0, SS(fs));			/* 1st sector of the FAT  */
		n = md;								/* Media descriptor byte */
		if (fmt != FS_FAT32) {
			n |= (fmt == FS_FAT12) ? 0x00FFFF00 : 0xFFFFFF00;
			ST_DWORD(tbl+0, n);				/* Reserve cluster #0-1 (FAT12/16) */
		} else {
			n |= 0xFFFFFF00;
			ST_DWORD(tbl+0, n);				/* Reserve cluster #0-1 (FAT32) */
			ST_DWORD(tbl+4, 0xFFFFFFFF);
			ST_DWORD(tbl+8, 0x0FFFFFFF);	/* Reserve cluster #2 for root dir */
		}
		if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
			return FR_DISK_ERR;
		mem_set(tbl, 0, SS(fs));			/* Fill following FAT entries with zero */
		for (n = 1; n < n_fat; n++) {		/* This loop may take a time on FAT32 volume due to many single sector writes */
			if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
				return FR_DISK_ERR;
		}
	}

	/* Initialize root directory */
	i = (fmt == FS_FAT32) ? au : n_dir;
	do {
		if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
			return FR_DISK_ERR;
	} while (--i);

#if _USE_ERASE	/* Erase data area if needed */
	{
		DWORD eb[2];

		eb[0] = wsect; eb[1] = wsect + (n_clst - ((fmt == FS_FAT32) ? 1 : 0)) * au - 1;
		disk_ioctl(pdrv, CTRL_ERASE_SECTOR, eb);
	}
#endif

	/* Create FSInfo if needed */
	if (fmt == FS_FAT32) {
		ST_DWORD(tbl+FSI_LeadSig, 0x41615252);
		ST_DWORD(tbl+FSI_StrucSig, 0x61417272);
		ST_DWORD(tbl+FSI_Free_Count, n_clst - 1);	/* Number of free clusters */
		ST_DWORD(tbl+FSI_Nxt_Free, 2);				/* Last allocated cluster# */
		ST_WORD(tbl+BS_55AA, 0xAA55);
		disk_write(pdrv, tbl, b_vol + 1, 1);	/* Write original (VBR+1) */
		disk_write(pdrv, tbl, b_vol + 7, 1);	/* Write backup (VBR+7) */
	}

	return (disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR;
}

在线仿真,发现函数在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系统的管理所占用的内存就非常大,要不就自己做小个小型的文件系统来实现这个功能。好吧,受教了。

时间: 2024-10-14 11:35:10

stm32—FatFs移植spi_flash(报错FR_NO_FILESYSTEM)的相关文章

嵌入式移植docker报错问题汇总

经过了漫长时间的移植和查询资料,得以解决一下嵌入式docker出现的问题,很多网上的资料全都是复制粘贴复制粘贴,找不到合适的解决方法让人很是苦恼,希望自己总结出的一些解决问题的经验给广大朋友减少一些负担吧! 1.standard文件找不到:解决方法: tar zcvf xtables /usr/lib64/xtables cp xtables.tar /work/initramfs/ 需要到同内核同系统的另一台服务器打包在解压 2.需要iptables支持才能启动docker,移植iptable

STM32下载报错invalid rom table

stm32单片机也用了蛮长时间了,这次遇到的小问题还是蛮有趣的,在这里分享给大家.一起共勉: 今天调试一个stm32板子和往常的习惯一样,会一部分一部分的焊接,今天调试发现下载程序时候报错:invalid rom table.复制到百度里面搜索发现 不是我第一个遇到这样的问题,请参考如下网页: http://blog.csdn.net/yufengzheyang/article/details/76954121 他们遇到超频的时候死掉的问题,我试了是拉高boot1,boot0低电平可以clear

【转】 grep 文件报错 “Binary file ... matches”

原文链接 http://blog.csdn.net/yaochunnian/article/details/7261006 grep 文件报错 “Binary file ... matches” 原因:文件为binary文件 解决:strings vers.log.2010-03-09 | grep -i ‘mezimedia’ 或者 grep -a -i ‘mezimedia’ vers.log.2010-03-09 grep命令是linux下的行过滤工具,其参数繁多,下面就一一介绍个个参数的

Laravel 项目登录报错:The MAC is invalid.

在 Laravel 项目完成部署到服务器.数据库导入成功后 后台登录报错: 谷歌一下,发现好些同样问题,看了看,有个很有意思: 我需要一个笑哭的表情来描述我现在的心情,clear artisan cache, clear composer cache, dump autoload, empty browser cahe -- still nothing.搞了这么一大串竟然是 still nothing. 好的,第一回抱着非常 happy 的心情调 Bug. 继续找,找啊找...... 咦,找到了

coures包下载和安装 可解决报错ImportError: No module named &#39;_curses&#39;

http://blog.csdn.net/liyaoqing/article/details/54949253 coures curses 库 ( ncurses )提供了控制字符屏幕的独立于终端的方法.curses 是大多数类似于 UNIX 的系统(包括Linux)的标准部分,而且它已经移植到 Windows 和其它系统. 安装包   http://www.lfd.uci.edu/~gohlke/pythonlibs/#curses 安装   pip install whl文件名 可以应对py

附加数据库报错:无法打开物理文件 XXX.mdf&quot;,操作系统错误 5:&quot;5(拒绝访问。)&quot;

今天在附加数据库的时候出现如图报错信息: 无法打开物理文件 XXX.mdf",操作系统错误 5:"5(拒绝访问.)"错信息如图:(是不是远程服务器数据库附加出现只读那个情况,也可以这样解决??,经测试,是这样的,不过远的用户是user,改成完全控制允许) 首先,我的数据库安装根目录和附加的数据库不是同一个目录,在安装数据库的时候根目录是默认的,为C盘下的目录,而我要附加的数据库的目录为E盘下,所以:解决方案一:使用windows账户登进,将被附加的数据库移植到根目录下,如图:

[转][JavaScript]使用jquery插件报错:$.browser is undefined的解决方法

刚开始以为是插件有错误,就到官方网站去下载一个最新版的Jcrop插件,结果在原项目的网页打开就是正常的,而引入项目就会报错,我发现可能与jquery的插件版本有关,查看官方的demo目录下的juqery版本是V1.3.2,而我使用的jquery版本是V1.11.1,查看jquery官方的更新日志,果然是这个的问题.关于$.browserbrowser就是用来获取浏览器基本信息的. jQuery 从 1.9 版开始,移除了 $.browser 和 $.browser.version , 取而代之的

【Note2】用keil对工程编译时,工程中已经包含的文件会报错:cannot open source input file usb_conf.h No such file or directory

错误举例: ..\..\Libraries\STM32_USB-FS-Device_Driver\inc\usb_type.h(21): error:  #5: cannot open source input file "usb_conf.h": No such file or directory 这是因为没有设置 STM32 固件库的目录, 编译器就默认到 "Keil"根目录下的某某目录找去了.如果现在编译程序,会报错的 解决方法:引用固件库文件所在的目录需要在

pb报错大全

string  ls_msgchoose case error.number case 1//by zero  ls_msg = "发生被 0 除错误" case 2//2 Null object reference   ls_msg = "空对象引用" case 3//3 Array boundary exceeded   ls_msg = "数组越界" case 4//4 Enumerated value is out of range fo