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

📄 uffs_public.c

📁 nandflash文件系统源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
    Copyright (C) 2005-2008  Ricky Zheng <ricky_gz_zheng@yahoo.co.nz>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

*/
/**
 * \file uffs_public.c
 * \brief public and miscellaneous functions
 * \author Ricky Zheng, created 10th May, 2005
 */

#include "uffs/uffs_types.h"
#include "uffs/uffs_config.h"
#include "uffs/uffs_core.h"
#include "uffs/uffs_device.h"
#include "uffs/uffs_os.h"

#include <string.h>

#define PFX "public:"


int uffs_GetFirstBlockTimeStamp(void)
{
	return 0;
}

int uffs_GetNextBlockTimeStamp(int prev)
{
	return (prev + 1) % 3;
}

UBOOL uffs_IsSrcNewerThanObj(int src, int obj)
{
	switch(src - obj) {
		case 0:
			uffs_Perror(UFFS_ERR_SERIOUS, PFX "the two block have the same time stamp ?\n");
			break;
		case 1:
		case -2:
			return U_TRUE;
		case -1:
		case 2:
			return U_FALSE;
		default:
			uffs_Perror(UFFS_ERR_SERIOUS, PFX "time stamp out of range !\n");
			break;
	}
	return U_FALSE;
}


//URET uffs_ECCCheck(uffs_Device *dev, uffs_Buf *buf)
//{
//	dev = dev;
//	return U_SUCC;
//}

/** 
 * \brief Calculate tag checksum
 * \param[in] tag input tag
 * \return checksum of tag
 */
u8 uffs_CalTagCheckSum(uffs_Tags *tag)
{
#if defined(ENABLE_TAG_CHECKSUM) && ENABLE_TAG_CHECKSUM == 1
	u8 checkSum = 0;
	int i;
	int ofs;

	ofs = (int)(&(((uffs_Tags *)NULL)->checkSum));

	for(i = 0; i < ofs; i++) {
		checkSum += *((u8 *)(tag) + i);
	}
	return checkSum;
#else
	tag = tag;
	return 0xff;
#endif
}


/** 
 * \brief find a best page than given page from page.
 * \param[in] dev uffs device
 * \param[in] bc block info
 * \param[in] page page number to be compared with
 * \return the better page number, could be the same with given page
 */
u16 uffs_FindBestPageInBlock(uffs_Device *dev, uffs_blockInfo *bc, u16 page)
{
	uffs_pageSpare *spare_old, *spare;
	int i;
	int best;

	if(page == dev->attr->pages_per_block - 1) return page;
	
	uffs_LoadBlockInfo(dev, bc, page); //load old page
	spare_old = &(bc->spares[page]);

	if(spare_old->tag.pageID == page) {
		//well, try to speed up ....
		uffs_LoadBlockInfo(dev, bc, dev->attr->pages_per_block - 1); 
		spare = &(bc->spares[dev->attr->pages_per_block - 1]);
		if(spare->tag.pageID == dev->attr->pages_per_block - 1) {
			return page;
		}
	}

	uffs_LoadBlockInfo(dev, bc, UFFS_ALL_PAGES);
	best = page;
	//the better page must be ahead of page, so ...i = page + 1; i < ...
	for(i = page + 1; i < dev->attr->pages_per_block; i++) {
		spare = &(bc->spares[i]);
		if(spare->tag.pageID == spare_old->tag.pageID) {
			if(	spare->tag.father == spare_old->tag.father &&
				spare->tag.serial == spare_old->tag.serial &&
				spare->tag.dirty == TAG_DIRTY && //0: dirty, 1:clear
				spare->tag.valid == TAG_VALID) { //0: valid, 1:invalid
				if(i > best) best = i;
			}
		}
	}
	return best;
}

/** 
 * \brief find a valid page with given pageID
 * \param[in] dev uffs device
 * \param[in] bc block info
 * \param[in] pageID pageID to be find
 * \return the valid page number which has given pageID
 * \retval >=0 page number
 * \retval UFFS_INVALID_PAGE page not found
 */
u16 uffs_FindPageInBlockWithPageId(uffs_Device *dev, uffs_blockInfo *bc, u16 pageID)
{
	u16 page;
	uffs_Tags *tag;

	//Indeed, the page which has pageID, should ahead of pageID ...
	for(page = pageID; page < dev->attr->pages_per_block; page++) {
		uffs_LoadBlockInfo(dev, bc, page);
		tag = &(bc->spares[page].tag);
		if(tag->pageID == pageID) return page;
	}
	return UFFS_INVALID_PAGE;
}

/** 
 * Are all the pages in the block used ?
 */
UBOOL uffs_IsBlockPagesFullUsed(uffs_Device *dev, uffs_blockInfo *bc)
{
	uffs_LoadBlockInfo(dev, bc, dev->attr->pages_per_block - 1);
	if(bc->spares[dev->attr->pages_per_block - 1].tag.dirty == TAG_DIRTY) return U_TRUE;

	return U_FALSE;
}

/** 
 * Is this block used ?
 * \param[in] dev uffs device
 * \param[in] bc block info
 * \retval U_TRUE block is used
 * \retval U_FALSE block is free
 */
UBOOL uffs_IsThisBlockUsed(uffs_Device *dev, uffs_blockInfo *bc)
{
	uffs_LoadBlockInfo(dev, bc, 0);
	if(bc->spares[0].tag.dirty == TAG_DIRTY) return U_TRUE;

	return U_FALSE;
}

/** 
 * get block time stamp from a exist block
 * \param[in] dev uffs device
 * \param[in] bc block info
 */
int uffs_GetBlockTimeStamp(uffs_Device *dev, uffs_blockInfo *bc)
{
	if(uffs_IsThisBlockUsed(dev, bc) == U_FALSE) 
		return uffs_GetFirstBlockTimeStamp();
	else{
		uffs_LoadBlockInfo(dev, bc, 0);
		return bc->spares[0].tag.blockTimeStamp;
	}

}

/** 
 * find first free page from 'pageFrom'
 * \param[in] dev uffs device
 * \param[in] bc block info
 * \param[in] pageFrom search from this page
 * \return return first free page number from 'pageFrom'
 * \retval UFFS_INVALID_PAGE no free page found
 * \retval >=0 the first free page number
 */
u16 uffs_FindFirstFreePage(uffs_Device *dev, uffs_blockInfo *bc, u16 pageFrom)
{
	u16 i;

	for(i = pageFrom; i < dev->attr->pages_per_block; i++) {
		uffs_LoadBlockInfo(dev, bc, i);
		if(uffs_IsPageErased(dev, bc, i) == U_TRUE)
			return i;
	}
	return UFFS_INVALID_PAGE; //free page not found
}


/** 
 * Find first valid page from a block, just used in mounting a partition
 */
u16 uffs_FindFirstValidPage(uffs_Device *dev, uffs_blockInfo *bc)
{
	u16 i;
	for(i = 0; i < dev->attr->pages_per_block; i++) {
		uffs_LoadBlockInfo(dev, bc, i);
		if(bc->spares[i].checkOk) return i;
	}
	return UFFS_INVALID_PAGE;
}

/** 
 * write data to a new page
 * \param[in] dev uffs device
 * \param[in] block block number to be wrote to
 * \param[in] page page number to be wrote to
 * \param[in] tag new page tag
 * \param[in] buf new page data
 */
URET uffs_WriteDataToNewPage(uffs_Device *dev, 
							 u16 block, 
							 u16 page,
							 uffs_Tags *tag,
							 uffs_Buf *buf)
{
	URET ret = U_SUCC;

	tag->dirty = 0;
	tag->valid = 1;
#if defined(ENABLE_TAG_CHECKSUM) && ENABLE_TAG_CHECKSUM == 1
	tag->checkSum = 0xff;
#endif

//	uffs_Perror(UFFS_ERR_NOISY, PFX"write b:%d p:%d t:%d f:%d s:%d id:%d L:%d\n",
//				block, page, buf->type, buf->father, buf->serial, buf->pageID, buf->dataLen);

	//step 1: write spare
	ret = dev->flash->WritePageSpare(dev, block, page, tag);
	if(ret != U_SUCC)
		return ret;
	
	//step 2: write page data
	dev->flash->MakeEcc(dev, buf->data, buf->ecc);
	ret = dev->ops->WritePageData(dev, block, page, buf->data, 0, dev->com.pgSize);
	if(ret != U_SUCC)
		return ret;

	//step 3: write spare again, make page valid
	tag->valid = 0;
#if defined(ENABLE_TAG_CHECKSUM) && ENABLE_TAG_CHECKSUM == 1
	tag->checkSum = uffs_CalTagCheckSum(tag); //calculate right check sum
#endif
	ret = dev->flash->MakePageValid(dev, block, page, tag);
	if(ret != U_SUCC)
		return ret;

	return U_SUCC;
}

///** 
// * \brief recover a page in block
// * \param[in] dev uffs device
// * \parma[in] bc block information buffer
// * \param[in] oldPage old page number

⌨️ 快捷键说明

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