📄 nand_util.c
字号:
}
return -1;
}
/***********************************************************************/
/* invalidate_ctrl_sects_upto: Invalidate all control sectors from */
/* beginning upto bad sector */
/* */
/* Input: bad_sect = sector to stop at */
/* */
/* Returns: First sector in next control block past bad one, */
/* FLAST_SECT if no such block */
/* */
/***********************************************************************/
static ui32 invalidate_ctrl_sects_upto(ui32 bad_sect)
{
ui32 sect, bad_block = bad_sect / Flash->block_sects;
/*-------------------------------------------------------------------*/
/* Mark all sectors from begining to bad sector as dirty. */
/*-------------------------------------------------------------------*/
sect = Flash->frst_ctrl_sect;
for (;;)
{
Flash->sect_tbl[sect].prev = FDRTY_SECT;
Flash->blocks[sect / Flash->block_sects].ctrl_block = FALSE;
/*-----------------------------------------------------------------*/
/* If we've reached the bad sector, stop. */
/*-----------------------------------------------------------------*/
if (sect == bad_sect)
break;
sect = Flash->sect_tbl[sect].next;
PfAssert(sect != FLAST_SECT);
}
/*-------------------------------------------------------------------*/
/* Get first control sector in next block past bad one. */
/*-------------------------------------------------------------------*/
while (sect != FLAST_SECT && sect / Flash->block_sects == bad_block)
sect = Flash->sect_tbl[sect].next;
return sect;
}
/***********************************************************************/
/* update_erase_set: Look for a block in erasable set, and if found, */
/* take it out and replace it with another one */
/* */
/* Input: block = bad block to take out of erasable set */
/* */
/***********************************************************************/
static void update_erase_set(ui32 block)
{
int s, best_block = -1, f_best_block = -1, f, b, i;
/*-------------------------------------------------------------------*/
/* Look for block in erasable set. */
/*-------------------------------------------------------------------*/
for (s = 0; s < Flash->set_blocks; ++s)
{
/*-----------------------------------------------------------------*/
/* If block in erasable set, take it out. */
/*-----------------------------------------------------------------*/
if (Flash->erase_set[s] == block)
{
for (b = 0; b < Flash->num_blocks; ++b)
if (!Flash->blocks[b].bad_block && !Flash->blocks[b].ctrl_block
&& Flash->sect_tbl[(b + 1) * Flash->block_sects - 1].prev !=
FFREE_SECT)
{
/*-----------------------------------------------------------*/
/* Check if block is in erasable set already. */
/*-----------------------------------------------------------*/
for (i = 0; i < Flash->set_blocks; ++i)
if (Flash->erase_set[i] == b)
break;
/*-----------------------------------------------------------*/
/* If block not in erase set see if it is a good candidate. */
/* When computing the selector function, ignore wear count. */
/*-----------------------------------------------------------*/
if (i == Flash->set_blocks)
{
f = (int)(16 * (Flash->block_sects -
Flash->blocks[b].used_sects) +
(Flash->high_wear - Flash->blocks[b].wear_count));
if (best_block == -1 || f_best_block < f)
{
best_block = b;
f_best_block = f;
}
}
}
/*---------------------------------------------------------------*/
/* If a replacement block found, use it. */
/*---------------------------------------------------------------*/
if (best_block != -1)
Flash->erase_set[s] = best_block;
/*---------------------------------------------------------------*/
/* Else the flash contains only free/bad blocks. Remove bad block*/
/* from erase set and replace it with the block containing the */
/* first free sector. */
/*---------------------------------------------------------------*/
else
Flash->erase_set[s] = (int)(Flash->free_sect/Flash->block_sects);
}
}
}
/***********************************************************************/
/* mark_block_bad: On a write sector failure, invalidate whole block */
/* */
/* Input: block = block to be marked bad */
/* */
/* Returns: 0 on success, -1 on error */
/* */
/***********************************************************************/
static int mark_block_bad(ui32 block)
{
ui32 sect, i;
/*-------------------------------------------------------------------*/
/* Mark block as bad. */
/*-------------------------------------------------------------------*/
Flash->blocks[block].bad_block = TRUE;
++Flash->bad_blocks;
Flash->blocks[block].ctrl_block = FALSE;
/*-------------------------------------------------------------------*/
/* Remove any free sectors from bad block and mark all non-data */
/* sectors as invalid. */
/*-------------------------------------------------------------------*/
sect = block * Flash->block_sects;
for (i = 0; i++ < Flash->block_sects; ++sect)
{
if (Flash->sect_tbl[sect].prev == FFREE_SECT)
{
if (Flash->free_sect != Flash->last_free_sect)
{
--Flash->free_sects;
Flash->free_sect = Flash->sect_tbl[sect].next;
Flash->sect_tbl[sect].prev = FNVLD_SECT;
}
else
{
PfAssert(FALSE); /*lint !e506, !e774*/
return -1;
}
}
else if (Flash->sect_tbl[sect].prev == FDRTY_SECT)
Flash->sect_tbl[sect].prev = FNVLD_SECT;
}
/*-------------------------------------------------------------------*/
/* Update erasable set if bad block is in there. */
/*-------------------------------------------------------------------*/
update_erase_set(block);
/*-------------------------------------------------------------------*/
/* If bad blocks exceeded maximum, error. */
/*-------------------------------------------------------------------*/
if (Flash->bad_blocks > Flash->max_bad_blocks)
{
set_errno(EIO);
return -1;
}
return 0;
}
/***********************************************************************/
/* free_ctrl_blocks_from: Free all control blocks from current sector */
/* */
/* Input: sect = sector to start at */
/* */
/***********************************************************************/
static void free_ctrl_blocks_from(ui32 sect)
{
ui32 next_sect, one_past_last_ctrl_sect = FLAST_SECT;
while (sect != FLAST_SECT)
{
next_sect = Flash->sect_tbl[sect].next;
/*-----------------------------------------------------------------*/
/* Mark sector as free. */
/*-----------------------------------------------------------------*/
Flash->sect_tbl[sect].prev = FFREE_SECT;
++Flash->free_sects;
Flash->blocks[sect / Flash->block_sects].ctrl_block = FALSE;
/*-----------------------------------------------------------------*/
/* If at end of block, add whole block to free list. */
/*-----------------------------------------------------------------*/
if (sect % Flash->block_sects == Flash->block_sects - 1)
{
Flash->sect_tbl[Flash->last_free_sect].next =
(ui16)(sect - Flash->block_sects + 1);
Flash->sect_tbl[sect].next = FLAST_SECT;
Flash->last_free_sect = sect;
one_past_last_ctrl_sect = FLAST_SECT;
}
else
{
Flash->sect_tbl[sect].next = (ui16)(sect + 1);
one_past_last_ctrl_sect = sect + 1;
}
sect = next_sect;
}
/*-------------------------------------------------------------------*/
/* If there are sectors left in last control block, mark them free. */
/*-------------------------------------------------------------------*/
if (one_past_last_ctrl_sect != FLAST_SECT)
for (sect = one_past_last_ctrl_sect;; ++sect)
{
/*---------------------------------------------------------------*/
/* Mark sector as free. */
/*---------------------------------------------------------------*/
Flash->sect_tbl[sect].prev = FFREE_SECT;
++Flash->free_sects;
/*---------------------------------------------------------------*/
/* If at end of block, add whole block to free list. */
/*---------------------------------------------------------------*/
if (sect % Flash->block_sects == Flash->block_sects - 1)
{
Flash->sect_tbl[Flash->last_free_sect].next =
(ui16)(sect - Flash->block_sects + 1);
Flash->sect_tbl[sect].next = FLAST_SECT;
Flash->last_free_sect = sect;
return;
}
else
Flash->sect_tbl[sect].next = (ui16)(sect + 1);
}
}
/***********************************************************************/
/* Global Function Definitions */
/***********************************************************************/
/***********************************************************************/
/* FsNandReadSect: Read a sector from the volume */
/* */
/* Inputs: buffer = buffer to place sector data into */
/* sect_num = sector to be read */
/* */
/* Returns: 0 on success, -1 on failure */
/* */
/***********************************************************************/
int FsNandReadSect(void *buffer, ui32 sect_num)
{
int i, rc = 0;
ui32 addr = Flash->mem_base + Flash->sect_sz * sect_num;
ui32 wear = Flash->blocks[sect_num / Flash->block_sects].wear_count;
/*-------------------------------------------------------------------*/
/* Read in a page at a time. */
/*-------------------------------------------------------------------*/
for (i = 0; i < Flash->pages_per_sect; ++i, addr += Flash->page_size)
{
rc |= Flash->driver.nand.read_page(buffer, addr, wear, Flash->vol);
buffer = (void *)((ui32)buffer + Flash->page_size);
}
return rc;
}
/***********************************************************************/
/* FsNandWriteType: Attempt to invalidate control sectors */
/* */
/* Inputs: sect_num = control sector to be invalidated */
/* type = sector type to be written for this sector */
/* */
/* Returns: 0 on success, -1 on failure, RWR_CTRL_OK if control */
/* was rewritten succesfully */
/* */
/***********************************************************************/
int FsNandWriteType(ui32 sect_num, ui32 type)
{
ui32 addr = Flash->mem_base + sect_num * Flash->sect_sz, bad_block;
ui32 frst_ctrl_sect, j, i;
FlashGlob *vol;
int status;
/*-------------------------------------------------------------------*/
/* Write sector type a page at a time. */
/*-------------------------------------------------------------------*/
for (i = 0; i < Flash->pages_per_sect; ++i, addr += Flash->page_size)
{
/*-----------------------------------------------------------------*/
/* Release exclusive access to the flash file system. */
/*-----------------------------------------------------------------*/
vol = Flash;
semPost(FlashSem);
/*-----------------------------------------------------------------*/
/* Write the type. */
/*-----------------------------------------------------------------*/
status = vol->driver.nand.write_type(addr, type, vol->vol);
/*-----------------------------------------------------------------*/
/* Acquire exclusive access to the flash file system. */
/*-----------------------------------------------------------------*/
semPend(FlashSem, WAIT_FOREVER);
Flash = vol;
/*-----------------------------------------------------------------*/
/* If chip error, mark whole block as bad. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -