FATFS支持英文长文件名

这段时间在做SD卡的驱动以及在此基础上增加FAT32文件系统.

SD卡目前使用SDHC 16G的TF卡,读写擦功能都支持.

那么FAT32文件系统,我们可以在网上找到开源的FAT文件系统这个文件系统,目前很多人都在使用.

移植方面很简单,只要实现diskio.c里面的几个函数就可以了.

另外,还有一个配置文件ffconf.h这个文件,主要配置一些功能.如是否支持长文件名,中文编码等等。


       所以我们要实现支持长的英文名字,是需要配置以下宏

/*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/---------------------------------------------------------------------------*/

#define _CODE_PAGE	437
/* This option specifies the OEM code page to be used on the target system.
/  Incorrect setting of the code page can cause a file open failure.
/
/   1   - ASCII (No extended character. Non-LFN cfg. only)
/   437 - U.S.
/   720 - Arabic
/   737 - Greek
/   771 - KBL
/   775 - Baltic
/   850 - Latin 1
/   852 - Latin 2
/   855 - Cyrillic
/   857 - Turkish
/   860 - Portuguese
/   861 - Icelandic
/   862 - Hebrew
/   863 - Canadian French
/   864 - Arabic
/   865 - Nordic
/   866 - Russian
/   869 - Greek 2
/   932 - Japanese (DBCS)
/   936 - Simplified Chinese (DBCS)
/   949 - Korean (DBCS)
/   950 - Traditional Chinese (DBCS)
*/


#define	_USE_LFN	3
#define	_MAX_LFN	255
/* The _USE_LFN option switches the LFN feature.
/
/   0: Disable LFN feature. _MAX_LFN has no effect.
/   1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
/   2: Enable LFN with dynamic working buffer on the STACK.
/   3: Enable LFN with dynamic working buffer on the HEAP.
/
/  When enable the LFN feature, Unicode handling functions (option/unicode.c) must
/  be added to the project. The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes.
/  When use stack for the working buffer, take care on stack overflow. When use heap
/  memory for the working buffer, memory management functions, ff_memalloc() and
/  ff_memfree(), must be added to the project. */


#define	_LFN_UNICODE	0
/* This option switches character encoding on the API. (0:ANSI/OEM or 1:Unicode)
/  To use Unicode string for the path name, enable LFN feature and set _LFN_UNICODE
/  to 1. This option also affects behavior of string I/O functions. */

然后将option目录下的syscall.c、unicode.c包含到工程里面.

由于需要支持到内存动态分配等原因,所以修改syscall.c文件的相关函数.如下图:


然后进行编译=======>通过!


然后,你写一个长文件名,如test0123456789.TXT,并往里面写内容.完全没有问题.读文件也是没有问题.

但是如果你要读文件的内容时,你要注意一下,因为你需要知道要读取的文件大小.也许你会使用

FRESULT f_stat (
	const TCHAR* path,	/* Pointer to the file path */
	FILINFO* fno		/* Pointer to file information to return */
)

通常代码,你会如下写

	FILINFO fno;
	if(f_stat( "0:Test1234567890.txt",&fno))
	{
			DEBUG_MSG(MAIN_DEBUG,("f_stat Fail !!!!\r\n"));
	}
	else
	{
		DEBUG_MSG(MAIN_DEBUG,("%s Size %d .\r\n",fno.fname,fno.fsize));
		if(f_open(&file, "0:Test1234567890.txt", FA_OPEN_EXISTING | FA_READ)) 
		{
			DEBUG_MSG(MAIN_DEBUG,("f_open File Fail .\r\n"));
		}
		else
		{
			char *pBuffer = malloc(fno.fsize);
			memset(pBuffer,0,fno.fsize);
			if(pBuffer)
			{
				u32 kk = 0;
				if(f_read(&file, pBuffer,fno.fsize, &bw))
				{
					DEBUG_MSG(MAIN_DEBUG,("f_read Fail !!!!\r\n"));
				}	
				while(kk < fno.fsize)
				{
					DEBUG_MSG(MAIN_DEBUG,("%c",pBuffer[kk++]));
				}
				DEBUG_MSG(MAIN_DEBUG,("\r\nRead Size %d .\r\n",bw));
				free(pBuffer);
				pBuffer = NULL;
			}

			f_close(&file);
		}	
	}

这个代码逻辑是没有什么大问题的.但是如果你用IAR debug方式,运行你会发现当程序异常了.

你深入调试会发现一个问题,文件大小竟然非常非常大.这个数值貌似没有赋值.

当你跟踪到如下代码

/*-----------------------------------------------------------------------*/
/* Get file information from directory entry                             */
/*-----------------------------------------------------------------------*/
#if _FS_MINIMIZE <= 1 || _FS_RPATH >= 2
static
void get_fileinfo (		/* No return code */
	DIR* dp,			/* Pointer to the directory object */
	FILINFO* fno	 	/* Pointer to the file information to be filled */
)
{
	UINT i;
	TCHAR *p, c;
	BYTE *dir;
#if _USE_LFN
	WCHAR w, *lfn;
#endif

	p = fno->fname;
	if (dp->sect) {		/* Get SFN */
		dir = dp->dir;
		i = 0;
		while (i < 11) {		/* Copy name body and extension */
			c = (TCHAR)dir[i++];
			if (c == ' ') continue;				/* Skip padding spaces */
			if (c == RDDEM) c = (TCHAR)DDEM;	/* Restore replaced DDEM character */
			if (i == 9) *p++ = '.';				/* Insert a . if extension is exist */
#if _USE_LFN
			if (IsUpper(c) && (dir[DIR_NTres] & (i >= 9 ? NS_EXT : NS_BODY)))
				c += 0x20;			/* To lower */
#if _LFN_UNICODE
			if (IsDBCS1(c) && i != 8 && i != 11 && IsDBCS2(dir[i]))
				c = c << 8 | dir[i++];
			c = ff_convert(c, 1);	/* OEM -> Unicode */
			if (!c) c = '?';
#endif
#endif
			*p++ = c;
		}
		fno->fattrib = dir[DIR_Attr];				/* Attribute */
		fno->fsize = LD_DWORD(dir + DIR_FileSize);	/* Size */
		fno->fdate = LD_WORD(dir + DIR_WrtDate);	/* Date */
		fno->ftime = LD_WORD(dir + DIR_WrtTime);	/* Time */
	}
	*p = 0;		/* Terminate SFN string by a \0 */

#if _USE_LFN
	if (fno->lfname) {
		i = 0; p = fno->lfname;
		if (dp->sect && fno->lfsize && dp->lfn_idx != 0xFFFF) {	/* Get LFN if available */
			lfn = dp->lfn;
			while ((w = *lfn++) != 0) {		/* Get an LFN character */
#if !_LFN_UNICODE
				w = ff_convert(w, 0);		/* Unicode -> OEM */
				if (!w) { i = 0; break; }	/* No LFN if it could not be converted */
				if (_DF1S && w >= 0x100)	/* Put 1st byte if it is a DBC (always false on SBCS cfg) */
					p[i++] = (TCHAR)(w >> 8);
#endif
				if (i >= fno->lfsize - 1) { i = 0; break; }	/* No LFN if buffer overflow */
				p[i++] = (TCHAR)w;
			}
		}
		p[i] = 0;	/* Terminate LFN string by a \0 */
	}
#endif
}
#endif /* _FS_MINIMIZE <= 1 || _FS_RPATH >= 2 */

你会发现“fno->lfsize”这个值很大。如果你一路从f_stat函数跟踪进来,你会知道这整个过程“fno->lfsize”都没有被赋值过.因此,解决这个问题的方法是,开始的时候对"FILINFO fno"进行赋值.可以写成"FILINFO fno = {0};"

至此,读文件内容也正常了.补充一点,当不支持长命名文件时,都是很正常(但或许存在风险,因此无论如何对该结构体变量都需要进行赋初值).



来自:http://blog.csdn.net/lan120576664

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值