⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fat12.c

📁 FAT12 文件系统,囊括了文件系统的各个函数,另外还包括了地址映射,适合读写NAND_FLASH
💻 C
📖 第 1 页 / 共 5 页
字号:
	lgToph[newlogicClusternum] = newphBlocknum;							//更新逻辑映射表
	
	tempSectorSpare[6]  = (BYTE)(newlogicClusternum & 0xff);			//准备写入新块的逻辑号
	tempSectorSpare[7]  = (BYTE)(newlogicClusternum>>8); 
	tempSectorSpare[11] = tempSectorSpare[6];
	tempSectorSpare[12] = tempSectorSpare[7];
	NAND_SpareProgram((newphBlocknum<<14) | 6, &tempSectorSpare[6], 2);	//在FLASH中将该新块的0扇区的逻辑号写入新物理块
	NAND_SpareProgram((newphBlocknum<<14) | 11, &tempSectorSpare[11], 2);//在FLASH中将该新块的0扇区的逻辑号写入新物理块	
	
	if(PrevLgClusterNum >= 2)
	{		
		Write_FAT(PrevLgClusterNum,newlogicClusternum);	//在FAT表中原逻辑号对应位置写入新逻辑号(链接到原逻辑号后)
	}
	
	Write_FAT(newlogicClusternum,0x0fff);				//在FAT表中新逻辑号对应位置写入0x0fff(文件的最后一簇)
	
	return newlogicClusternum;							//返回簇号
	
} 


/***************************  函数GetNextLgClusterNum(WORD LgClusterNum) ****************************/
/* 功能:根据输入的逻辑镞号得到与它链接的下一个逻辑镞号												*/
/* 入口参数:逻辑镞号,不能小于2																	*/
/* 出口参数:与输入逻辑镞号链接的下一个逻辑镞号,如果为0xffff表示没有下一个镞号						*/
/* 说明:非用户使用函数																				*/
/****************************************************************************************************/
WORD GetNextLgClusterNum(WORD LgClusterNum)//OK
{
	return(Read_FAT(LgClusterNum));
}


/****************************** 函数 FreeCluster(WORD StartLgClusterNum) ****************************/
/* 功能:根据输入的逻辑镞号依次释放fat链,更新FAT表和逻辑映射表,同时擦除被释放的逻辑簇号所对应的物理块*/
/* 入口参数:逻辑镞号,不能小于2																	*/
/* 出口参数:无																						*/
/* 说明:非用户使用函数																				*/
/****************************************************************************************************/
void FreeCluster(WORD StartLgClusterNum)//OK
{
	WORD nextclusternum, startclusternum;
	
	nextclusternum = StartLgClusterNum;
	startclusternum = StartLgClusterNum;
	
	while(nextclusternum != 0x0fff)
	{
		nextclusternum = Read_FAT(startclusternum);		//读FAT表中对应起始逻辑号的对应扇区内容
		Write_FAT(startclusternum,0);
		
		NAND_BlockErase(lgToph[startclusternum]);		//擦除被释放的物理块
		lgToph[startclusternum] = 0xffff;				//更新逻辑表
		
		startclusternum = nextclusternum;
	}
}





/*********** 函数 int AllocDir(DWORD LgParentDirSectorNum, DIRENTRY* new_dir, _FILE * fp) ***********/
/* 功能:	从目录区中寻找一个空目录项并将已经存放在new_dir中的目录(或文件)信息写入,同时将找到的目	*/
/*			录扇区号和在该扇区中的目录偏移号写到文件指针fp中										*/
/*入口参数:DWORD LgParentDirSectorNum,父目录扇区。准备从该扇区开始创建目录项,取值为>33表示从根目录区*/
/*			创建,或>=64表示从指定的扇区创建目录,其它值无效。但该扇区对应的簇事先应该在文件链表中	*/
/*			DIRENTRY* new_dir-- 除了其始簇外已经赋好值的目录项,即将被写入目录区					*/
/*			_FILE * fp-- 准备更新目录扇区号和偏移号的文件											*/
/* 出口参数:	0--成功; 1--根目录区已满; 4--没有空镞												*/
/* 说明:非用户使用函数																				*/
/****************************************************************************************************/
/*******************************************************************************
* 修改时间: 2007/09/11 14:12 by shenwf
* 修改原因: 申请新的一组文件的时候没有清零剩下的数据;
*******************************************************************************/
int AllocDir(DWORD LgParentDirSectorNum, DIRENTRY* new_dir, _FILE * fp)//OK
{
	DIRENTRY *dir;
	BYTE* Cache;
	BYTE sectornumber;
	WORD PrevCluster;
	WORD LgCluster;
	DWORD DirSectorNum = LgParentDirSectorNum;
	BYTE tempbuffer[512];


	if((DirSectorNum >= FirstDirSector) && (DirSectorNum < (FirstDirSector + RootDirSectors)))	//在根目录区
	{
		for(sectornumber = FirstDirSector; sectornumber < (FirstDirSector + RootDirSectors); sectornumber++)		
		{																		
			Cache = ReadLgSector(sectornumber,tempbuffer);						//读取该扇区的512个字节数据到tempbuffer中
						
			for(dir = (DIRENTRY *)Cache; (BYTE*)dir < (Cache + BytesPerSector); dir++)//在一个扇区内循环寻找空目录项
			{//中间部分Cache指针指向tempbuffer的起始位置,加512后即为dir的右边界
				if((dir->deName[0] == 0) || (dir->deName[0] == 0xe5))			//本项未用或文件被删除,也就是该目录项空,可以使用
				{
					memcpy((BYTE *)dir, (BYTE *)new_dir, sizeof(DIRENTRY));		//将新的目录信息写入tempbuffer中				
					WriteLgSector(sectornumber,tempbuffer);						//更新根目录区
					if(fp)														//更新文件信息
					{
						fp->DirSectorNum = sectornumber;						//当前目录项所在的扇区地址
						fp->DirIndex = ((BYTE*)dir - Cache) / sizeof(DIRENTRY); //目录索引,即该扇区中第x个目录项
						memcpy((BYTE *)(&fp->dir), (BYTE *)new_dir, sizeof(DIRENTRY));//新的目录信息写到文件结构中
					}
					return 0;													//操作成功,退出
				}
			}
		}
		
		return 1; 																//根目录区已满.
	}
	else																		//不在根目录区,此时ParentDirSectorNum应该大于等于64,进入数据区
	{
		LgCluster = SectorNumToClusterNum(LgParentDirSectorNum);				//计算LgParentDirSectorNum所在逻辑镞号
		
		while(LgCluster != 0x0fff)
		{
			for(sectornumber=0; sectornumber< SectorsPerCluster; sectornumber++)//在整个簇中搜索
			{
				Cache = ReadLgSector((LgCluster<<5)|sectornumber,tempbuffer);	//读取该扇区的512个字节数据到tempbuffer中
								
				for(dir = (DIRENTRY *)Cache; (BYTE*)dir < (Cache + BytesPerSector); dir++)
				{
					if((dir->deName[0] == 0) || (dir->deName[0] == 0xe5))		//本项未用或文件被删除,也就是该目录项空,可以使用
					{
						memcpy((BYTE *)dir, (BYTE *)new_dir, sizeof(DIRENTRY));	//将新的目录信息写入tempbuffer中	
						WriteLgSector((LgCluster<<5)|sectornumber,tempbuffer);	//更新FLASH中该扇区
						
						if(fp)													//更新文件信息
						{
							fp->DirSectorNum = (LgCluster<<5)|sectornumber;//DirSectorNum;  by LJC					//当前目录项所在的扇区地址
							fp->DirIndex = ((BYTE*)dir - Cache) / sizeof(DIRENTRY);//目录索引,即该扇区中第x个目录项
							memcpy((BYTE *)(&fp->dir), (BYTE *)new_dir, sizeof(DIRENTRY));//新的目录信息写到文件结构中
						}
						return 0;												//操作成功,退出
					}
				}
			}
			// 搜索完当前簇,没有空的目录项 
			PrevCluster = LgCluster;
			LgCluster = GetNextLgClusterNum(LgCluster);							//从FAT表中找出下一簇
		}
		
		//以上已经是文件链表中最后一个簇,需要一个空镞来创建一个新的目录扇区
		
		LgCluster = AllocCluster(PrevCluster);									//利用FAT表获得一个空簇
		if(LgCluster == 0xffff)													//没有空簇则返回
		{	return 4;	}
		
		//Cache = ReadLgSector(LgCluster<<5,tempbuffer);							//读取空簇0扇区的512个字节数据到tempbuffer中
		memset(tempbuffer,0,BytesPerSector);
		Cache = tempbuffer;
				
		dir = (DIRENTRY *)Cache;
		
		memcpy((BYTE *)dir, (BYTE *)new_dir, sizeof(DIRENTRY));
		WriteLgSector(LgCluster<<5,tempbuffer);									//更新FLASH中该扇区
		// 清理剩下的扇区的文件  by shenwf
		memset(tempbuffer,0,BytesPerSector);
		for( sectornumber = 1; sectornumber < SectorsPerCluster; sectornumber++)
		{
			WriteLgSector((LgCluster<<5)|sectornumber,tempbuffer);// 清零剩下的扇区中的数据;		
		}
		/////////////
		
		if(fp)
		{
			fp->DirSectorNum = LgCluster<<5;
			fp->DirIndex = ((BYTE*)dir - Cache) / sizeof(DIRENTRY);
			memcpy((BYTE *)(&fp->dir), (BYTE *)new_dir, sizeof(DIRENTRY));
		}
		
		return 0;
	}
}



/************************************** 函数 int DeleteDir(_FILE *file) *****************************/
/* 功能:	删除一个目录(文件),只将该文件的目录项标记为删除										*/
/*入口参数: _FILE *file,指向一个待删除的目录(文件)的指针											*/
/* 出口参数:无																						*/
/* 说明:非用户使用函数																				*/
/****************************************************************************************************/
int DeleteDir(_FILE *file)//OK
{
	BYTE* Cache;
	DIRENTRY *dir;
	DWORD secnum;
	BYTE tempbuffer[512];
	
	secnum = file->DirSectorNum;
	Cache = ReadLgSector(secnum,tempbuffer);						//获得文件目录区的扇区内容
	if(Cache == NULL)
	{	return 1;	}

	dir = (DIRENTRY *)Cache;
	dir += file->DirIndex;											//找到该文件的目录项位置

	dir->deName[0] = 0xe5;											//做删除标记
	WriteLgSector(secnum,tempbuffer);								//更新该文件的目录项
	return 0;
}



/*************************** 函数 char* get_valid_format(const char *fullpath) **********************/
/* 功能:	将输入的非存储格式的路径标准化成存储格式的路径,输入的路径名格式应为[\aaaa\aaa.bb],标准 */
/*			化后的存储格式为[\aaaa_ _ _ _ _ _ _\aaa_ _ _ _ _ bb _]									*/
/* 入口参数:文件的路径名。要求路径名的第一个字符必须是[\],最后一个字符不能为[\]					*/
/*			同时文件名称不能用中文,名称用8个英文字符,扩展名3个字符,总的路径字符小于80个			*/
/* 出口参数:static_path[512]中存放整个标准化后的路径,各层路径中不满11个字符时用空格填充;如果输入非法*/
/*			则返回空																				*/
/* 说明:   非用户使用函数																			*/
/****************************************************************************************************/
char* get_valid_format(const char *fullpath)//OK
{
	static char static_path[512];
	char* pstatic=static_path;
	char path[80];
	char* ppath = path;
	int dir_len_count = 0;					 							//路径长度.
	int i;

	if(fullpath == NULL || strlen(fullpath) >=80 || *fullpath != '\\')	//第一个字符必须是‘\’,路径长度不能大于80个字符
		{ return NULL; }

	if(strlen(fullpath) > 1 && fullpath[strlen(fullpath)-1] =='\\')		//最后一个字符是‘\’不允许
		{ return NULL; }

	strcpy(path, fullpath);												//将路径拷贝到path[80]数组

	memset(pstatic, 0, 512);											//将static_path[512]数组清零

	for(;;)
	{
		switch(*ppath)
		{
		case 0x00:														//结束符
			{
				if(dir_len_count != 0) 									// 前导字符不是'\\',说明确实到了路径的结束位置
				{
					for(i=0; i<(11 - dir_len_count); i++)				//此时如果文件名长度未满11字节,用blank填充未满11个的static_path[]位置
					{
						*pstatic = 0x20;
						pstatic++;
					}
				}
			}
			return static_path;											//返回整个字符串

		case '\\':
			{
				if(pstatic != static_path) 								//此时检验的已不是第一个字符,
				{
					if(dir_len_count == 0)								//但文件长度为0,说明开始检验第二个字符。但又出现 '\\',
						return NULL;									//说明输入的文件路径出现了不只一个'\\",此时无效

					for(i=0; i<(11 - dir_len_count); i++)
					{
						*pstatic = 0x20;								//如果检验的不是第1和第2个字符,说明一小段路径名已到结尾,要到下一段,
						pstatic++;										//则将后续的不满11个的static_path[]位置填充空格
					}
				}
				
				*pstatic = '\\';										//如果此时检验的是一小段路径的起始位置,则将static_path[]="\"
				pstatic++;
				
				ppath++;
				dir_len_count =0;										//在检测到’\\'之后,开始新的文件名计数,字符"\"不计长度
				continue;
			}
			//break;

		case '.':
			{
				if(dir_len_count > 8 || dir_len_count ==0) 				// 文件名长度不能超过8个字符,并且在"\"之后不能马上出现"."
					return NULL;

				if(ppath[1] == '.' || ppath[1] == '\\') 				// 不能出现两个以上的 '.'或 '.\'
					return NULL;

				for(i=0; i<(8 - dir_len_count); i++)					//出现'.'之后 static_path[]中用空格添充未满8个字符的位置
				{
					*pstatic = 0x20;
					pstatic++;
				}

				dir_len_count = 8;										//此时'.'之前的文件名有效,长度计8
				ppath++;
				continue;
			}
			//break;
			
		//以下为非法字符
		case 0x22:		//是"""号		
		case 0x2A:		//是"*"号
		case 0x2B:		//是"+"号
		case 0x2C:		//是","号
		case 0x2F:		//是"/"号
		case 0x3A:		//是":"号
		case 0x3B:		//是";"号
		case 0x3C:		//是"<"号
		case 0x3D:		//是"="号
		case 0x3E:		//是">"号
		case 0x3F:		//是"?"号
		case 0x5B:		//是"["号
		case 0x5D:		//是"]"号
		case 0x7C:		//是"|"号
			return NULL;

		default:
			{
				if(*ppath < 0x20)		//如果输入的字符都是ASCII表中空格以前的字符,都无效
					return NULL;				
			}
			break;
		}

		*pstatic = *ppath;				//如果输入的字符都不是以上的各种情况,说明字符有效,则将该字符送入static_path[]中
		dir_len_count ++;				//文件名称长度加1

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -