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

📄 fsmwritetask.c

📁 norflash的文件系统。 用于中低端手机开发的参考
💻 C
📖 第 1 页 / 共 5 页
字号:
					(uint8 *)&SectorStatus,
					OldSectorAddr + FIELD_OFFSET(FsmFlashSectorHdrT, Status),
					FIELD_SIZE(FsmFlashSectorHdrT, Status)
					);		

	if(ret != ERR_NONE)
		return ret;

	/* appended sector state to valid */
	SectorStatus = SECTOR_VALID;
	ret = DevWrite( DevP,
					(uint8 *)&SectorStatus,
					AppendSectorAddr + FIELD_OFFSET(FsmFlashSectorHdrT, Status),
					FIELD_SIZE(FsmFlashSectorHdrT, Status)
					);

	if(ret != ERR_NONE)
		return ret;

	/* new sector state to valid */
	SectorStatus = SECTOR_VALID;
	ret = DevWrite( DevP, 
					(uint8 *)&SectorStatus, 
					NewSectorAddr + FIELD_OFFSET(FsmFlashSectorHdrT, Status), 
					FIELD_SIZE(FsmFlashSectorHdrT, Status)
					);

	if(ret != ERR_NONE)
		return ret;

	/* old sector state to invalid */
	SectorStatus = SECTOR_INVALID;
	ret = DevWrite( DevP,
					(uint8 *)&SectorStatus,
					OldSectorAddr + FIELD_OFFSET(FsmFlashSectorHdrT, Status),
					FIELD_SIZE(FsmFlashSectorHdrT, Status)
					);		

	if(ret != ERR_NONE)
		return ret;

	BlkNum = (uint16)(OldPsn / MediaObjP->SectorsPerBlock);

	if (FsmGetMtxSem(MediaObjP->InfoLock) != ERR_NONE)
	{
		return ERR_SYSTEM;
	}

	MediaObjP->BlockInfoP[BlkNum].DirtySectors++;
	MediaObjP->BlockInfoP[BlkNum].UsedSectors--;

	if (FsmReleaseMtxSem(MediaObjP->InfoLock) != ERR_NONE)
	{
		return ERR_SYSTEM;
	}

	return ERR_NONE;
}


/********************************************************************
*	GetFreeEntry
*     Find an available directory entry
*     and return the address of the directory entry.
*
*	Input:
*
*	Output:
*			The address of the free directory entry.
*	return:
*		success:	ERR_NONE.
*		failure:	error code.
*********************************************************************/

static uint32 GetFreeEntry(
	FsmQueueItemT * ItemP, 
	uint32 * AddrP
	)
{

	uint32				i;

	uint32				ret;
	uint16				EntryStatus;

	uint16				EntrySize;
	uint16				EntriesPerSector;
	uint16				MaxDirtyCnt = 0;
	uint16				CurDirtyCnt = 0;

	uint32				offset;
	uint32				size;

	uint32				EntryAddr;

	uint32				OldSectorAddr;
	uint32				DirtiestLsn = (uint32)(-1);
	uint32				TempPsn;
	uint32				TempLsn;
	uint32				PrntLsn;

	FsmFlashMediaT *	MediaObjP;

	DEV_READ_FUNCPTR	DevRead;

	FsmDevObjHdrT *		DevP;


	ret = ERR_NONE;


	if (ItemP->type == QUEUE_FILE_DIR)
	{
		FsmDfsFileDescriptorT *	FdP;

		FdP = &FsmDfsFds[ItemP->ItemFd.fd];
		DevP = FdP->FdHdr.DevObjP;
		MediaObjP = (FsmFlashMediaT * )DevP->MediaObjP;
		PrntLsn = FdP->ParentDirFirstLsn;

		EntrySize = sizeof(FsmFileDirEntryT);
		offset    = FIELD_OFFSET(FsmFileDirEntryT, Status);
		size      = FIELD_SIZE(  FsmFileDirEntryT, Status);
	}
	else
	{
		DevP = FsmDataItemDevObjP;
		MediaObjP = (FsmFlashMediaT * )DevP->MediaObjP;
		PrntLsn = 1;

		EntrySize = sizeof(FsmItemDirEntryT);
		offset    = FIELD_OFFSET(FsmItemDirEntryT, Status);
		size      = FIELD_SIZE(  FsmItemDirEntryT, Status);
	}

	EntriesPerSector = (uint16)(MediaObjP->SectorSize / EntrySize);

	DevRead = DevP->DevDrvP->FsmDevRead;

	TempLsn = PrntLsn;

	DirtiestLsn = (uint32)(-1);

	for ( MaxDirtyCnt = 0; TempLsn != (uint32)(-1); )
	{
		CurDirtyCnt = 0;

		TempPsn = DfsLsn2Psn(MediaObjP, TempLsn);
		OldSectorAddr = DfsPsn2Addr(MediaObjP, TempPsn);

		EntryAddr = OldSectorAddr+ sizeof(FsmFlashSectorHdrT);

		for (i = 0; i < EntriesPerSector; i++, EntryAddr += EntrySize)
		{
			EntryStatus = 0;

			ret = DevRead( DevP, 
						   (uint8 *)&EntryStatus, 
						   EntryAddr + offset,
						   size
						   );

			if(ret != ERR_NONE)
				return ret;

			if (EntryStatus == ENTRY_EMPTY)
			{
				*AddrP = EntryAddr;
				return ERR_NONE;
			}
			else if (EntryStatus == ENTRY_INVALID)
			{
				CurDirtyCnt++;
			}
		}
		if (CurDirtyCnt > MaxDirtyCnt)
		{
			MaxDirtyCnt = CurDirtyCnt;
			DirtiestLsn = TempLsn;
		}

		/* Get Next Lsn. */
		ret = DevRead( DevP,
				 	   (uint8 *)&TempLsn, 
					   OldSectorAddr + FIELD_OFFSET(FsmFlashSectorHdrT, NextLsn),
					   FIELD_SIZE(FsmFlashSectorHdrT, NextLsn)
					   );

		if(ret != ERR_NONE)
			return ret;
	}


	if (MaxDirtyCnt != 0)
	{
		ret = DirModify(DevP, PrntLsn, AddrP, ItemP->type, DirtiestLsn);
	}
	else
	{
		ret = DirAppend(DevP, PrntLsn, AddrP, ItemP->type);
	}

	return ret;
}


/********************************************************************
*	GetValidEntry
*     Find the matched directory entry, matching pattern
*     may be a file name or data item type-id pair.
*
*	Input:
*
*	Output:
*			The address of the matched directory entry.
*	return:
*		success:	ERR_NONE.
*		failure:	error code.
*********************************************************************/

static uint32 GetValidEntry(
	FsmQueueItemT * ItemP, 
	uint32 * AddrP
	)
{
	uint32				i, j;

	uint32				ret;
	uint32				EntriesPerSector;
	uint32				TempLsn;
	uint32				TempPsn;
	uint32				OldSectorAddr;

	uint32				EntryAddr;

	FsmDevObjHdrT *		DevP;
	FsmFlashMediaT *	MediaObjP;

	DEV_READ_FUNCPTR	DevRead;


	if (ItemP->type == QUEUE_FILE_DIR)
	{
		FsmDfsFileDescriptorT *	FdP;

		FsmFileDirEntryT	FileEntry;
		char *				NameP;

		FdP = &FsmDfsFds[ItemP->ItemFd.fd];
		DevP = FdP->FdHdr.DevObjP;
		MediaObjP = (FsmFlashMediaT * )DevP->MediaObjP;
		TempLsn = FdP->ParentDirFirstLsn;

		i = strlen(FdP->PathName);
		while(i > 0)
		{
			if((FdP->PathName[i - 1] == '/') || (FdP->PathName[i - 1] == '\\'))
			{
				break;
			}
			i--;
		}

		NameP = ((char *)(&FdP->PathName[i]));

		EntriesPerSector = MediaObjP->SectorSize / sizeof(FsmFileDirEntryT);

		DevRead = DevP->DevDrvP->FsmDevRead;

		for ( ; TempLsn != (uint32)(-1); )
		{
			TempPsn = DfsLsn2Psn(MediaObjP, TempLsn);
			OldSectorAddr = DfsPsn2Addr(MediaObjP, TempPsn);

			EntryAddr = OldSectorAddr + sizeof(FsmFlashSectorHdrT);

			for ( i = 0; i < EntriesPerSector;
							i++, EntryAddr += sizeof(FsmFileDirEntryT))
			{
				FileEntry.Status = 0;

				ret =	DevRead( DevP, 
								 (uint8 *)&FileEntry, 
								 EntryAddr, 
								 sizeof(FsmFileDirEntryT)
								 );

				if(ret != ERR_NONE)
					return ret;

				if (FileEntry.Status == ENTRY_VALID)
				{
					for ( j = 0; j < FIELD_SIZE(FsmFileDirEntryT, FileName); j++)
					{
						if (FileEntry.FileName[j] != NameP[j])
						{
							break;
						}
						else if (FileEntry.FileName[j] == '\0')
						{
							*AddrP = EntryAddr;

							return ERR_NONE;
						}
					}

					if(j == FIELD_SIZE(FsmFileDirEntryT, FileName))
					{
						if(NameP[j] == '\0')
						{
							*AddrP = EntryAddr;

							return ERR_NONE;
						}
					}
				}
				else if (FileEntry.Status == ENTRY_EMPTY)
				{
					break;
				}
			}

			ret =	DevRead( DevP, 
							 (uint8 *)&TempLsn, 
							 OldSectorAddr + FIELD_OFFSET(FsmFlashSectorHdrT, NextLsn), 
							 FIELD_SIZE(FsmFlashSectorHdrT, NextLsn)
							 );

			if(ret != ERR_NONE)
				return ret;
		}
	}
	else
	{
		FsmItemDirEntryT	ItemEntry;

		DevP = FsmDataItemDevObjP;
		MediaObjP = (FsmFlashMediaT * )DevP->MediaObjP;
		TempLsn = 1; /* ParentDir first lsn for data item; */

		EntriesPerSector = MediaObjP->SectorSize / sizeof(FsmItemDirEntryT);

		DevRead = DevP->DevDrvP->FsmDevRead;

		for ( ; TempLsn != (uint32)(-1); )
		{
			TempPsn = DfsLsn2Psn(MediaObjP, TempLsn);
			OldSectorAddr = DfsPsn2Addr(MediaObjP, TempPsn);

			EntryAddr = OldSectorAddr + sizeof(FsmFlashSectorHdrT);

			for ( i = 0; i < EntriesPerSector; 
							i++, EntryAddr += sizeof(FsmItemDirEntryT))
			{
				ItemEntry.Status = 0;

				ret =	DevRead( DevP, 
								 (uint8 *)&ItemEntry, 
								 EntryAddr, 
								 sizeof(FsmItemDirEntryT)
								 );

				if(ret != ERR_NONE)
					return ret;

				if (ItemEntry.Status == ENTRY_VALID)
				{
					if ((ItemEntry.ItemType == ItemP->ItemFd.Item.ItemType) 
						&& (ItemEntry.ItemId == ItemP->ItemFd.Item.ItemId))
					{
						*AddrP = EntryAddr;

						return ERR_NONE;
					}
				}
				else if (ItemEntry.Status == ENTRY_EMPTY)
				{
					break;
				}
			}

			ret = DevRead( DevP, 
						   (uint8 *)&TempLsn, 
						   OldSectorAddr + FIELD_OFFSET(FsmFlashSectorHdrT, NextLsn),
						   FIELD_SIZE(FsmFlashSectorHdrT, NextLsn)
						   );

			if(ret != ERR_NONE)
				return ret;
		}
	}
	
	return ERR_NOTEXIST;
}



/********************************************************************
*	MultiInstanceCreate
*     Create a multi-instance data item.
*
*	Input:
*
*	Output:
*			
*	return:
*		success:	ERR_NONE.
*		failure:	error code.
*********************************************************************/

static uint32 MultiInstanceCreate(
	FsmQueueItemT * ItemP, 
	FsmDevObjHdrT * DevP)
{
	uint8				MultiInstStatus;
	uint32				temp1;
	uint16				temp2;

	uint32				ret;
	uint32				NewLsn;
	uint32				NewPsn;
	uint32				WriteOffset;
	uint32				NewEntryAddr;
	uint32				NewSectorAddr;

	FsmFlashSectorHdrT	SectorHdr;
	FsmItemDirEntryT	ItemEntry;

	FsmFlashMediaT *	MediaObjP;

	DEV_WRITE_FUNCPTR	DevWrite = DevP->DevDrvP->FsmDevWrite;

	MediaObjP = (FsmFlashMediaT * )DevP->MediaObjP;

	ret = GetFreeEntry(ItemP, &NewEntryAddr);
	if (ret != ERR_NONE)
	{
		return ret;
	}

	ret = GetFreeLsn(DevP, &NewLsn);
	if (ret != ERR_NONE)
	{
		return ret;
	}

	ret = GetFreePsn(DevP, &NewPsn);
	if (ret != ERR_NONE)
	{
		return ret;
	}

	NewSectorAddr = DfsPsn2Addr(MediaObjP, NewPsn);

	/* Sector state to writing */
	SectorHdr.Status  = SECTOR_WRITING;
	ret = DevWrite( DevP,
					(uint8 *)&SectorHdr.Status,
					NewSectorAddr + FIELD_OFFSET(FsmFlashSectorHdrT, Status),
					FIELD_SIZE(FsmFlashSectorHdrT, Status)
					);

	if(ret != ERR_NONE)
		return ret;

	SectorHdr.Type    = SECTOR_TYPE_MID;
	SectorHdr.Lsn     = NewLsn;
	SectorHdr.NextLsn = (uint32)(-1);	/* 0xFFFFFFFF */

	/* building the new sector header. */
	ret = DevWrite( DevP,
					(uint8 *)&SectorHdr, 
					NewSectorAddr, 
					sizeof(FsmFlashSectorHdrT)
					);

	if(ret != ERR_NONE)
		return ret;

	temp1 = MediaObjP->SectorSize - FIELD_SIZE(FsmMultiInstanceT, Length);
	temp2 = (uint16)(ItemP->length + (FIELD_SIZE(FsmMultiInstanceT, Status))); /* sizeof(uint8); */

	temp1 = (temp1 / temp2) * (FIELD_SIZE(FsmMultiInstanceT, Status)/*sizeof(uint8)*/);

	WriteOffset = temp1 + FIELD_SIZE(FsmMultiInstanceT, Length);

	/* write data to flash. */
	ret = DevWrite( DevP, 
					(uint8 *)(ItemP + 1), 
					NewSectorAddr + sizeof(FsmFlashSectorHdrT) + WriteOffset, 
					ItemP->length
					);

	if(ret != ERR_NONE)
		return ret;

	/* Multi-Instance data is ready now. */
	MultiInstStatus = INSTANCE_VALID;
	ret = DevWrite( DevP, 
					(uint8 *)&MultiInstStatus, 
					NewSectorAddr + sizeof(FsmFlashSectorHdrT)		\
						+ FIELD_OFFSET(FsmMultiInstanceT, Status[0]),
					FIELD_SIZE(FsmMultiInstanceT, Status)
					);

	if(ret != ERR_NONE)
		return ret;

	/* length of every instance. */
	temp2 = (uint16)ItemP->length;
	ret = DevWrite( DevP, 
					(uint8 *)&temp2, 
					NewSectorAddr + sizeof(FsmFlashSectorHdrT)		\
						+ FIELD_OFFSET(FsmMultiInstanceT, Length), 
					FIELD_SIZE(FsmMultiInstanceT, Length)
					);

	if(ret != ERR_NONE)
		return ret;

	/* Update the Lsn to Psn map information for the new sector. */
	if (FsmGetMtxSem(MediaObjP->MapTblLock) != ERR_NONE)
	{
		return ERR_SYSTEM;
	}
	MediaObjP->Lsn2PsnP[NewLsn] = NewPsn;
	if (FsmReleaseMtxSem(MediaObjP->MapTblLock) != ERR_NONE)
	{
		return ERR_SYSTEM;
	}

	/* sector state to allocated */
	SectorHdr.Status = SECTOR_ALLOCATED;
	ret = DevWrite( DevP, 
					(uint8 *)&SectorHdr.Status, 
					NewSectorAddr + FIELD_OFFSET(FsmFlashSectorHdrT, Status), 
					FIELD_SIZE(FsmFlashSectorHdrT, Status)
					);

	if(ret != ERR_NONE)
		return ret;

	/* entry state to writing */
	ItemEntry.Status = ENTRY_WRITING;
	ret = DevWrite( DevP,
					(uint8 *)&ItemEntry.Status, 
					NewEntryAddr + FIELD_OFFSET(FsmItemDirEntryT, Status),
					FIELD_SIZE(FsmItemDirEntryT, Status)
					);

	if(ret != ERR_NONE)
		return ret;

	ItemEntry.Status   = ENTRY_WRITING;
	ItemEntry.Type     = ENTRY_TYPE_ITEM;
	ItemEntry.ItemType = ItemP->ItemFd.Item.ItemType;
	ItemEntry.ItemId   = ItemP->ItemFd.Item.ItemId;
	ItemEntry.Method   = METHOD_MULTI;
	ItemEntry.Length   = ItemP->length;
	ItemEntry.FirstLsn = NewLsn;

⌨️ 快捷键说明

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