📄 uffs_public.c
字号:
/*
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 + -