📄 nand_util.c
字号:
crc = CRC_UPDATE(crc, Flash->tmp_sect[j - 2]);
crc = CRC_UPDATE(crc, Flash->tmp_sect[j - 1]);
}
else
while (j < Flash->sect_sz)
{
Flash->tmp_sect[j++] = 0xFF;
crc = CRC_UPDATE(crc, 0xFF);
}
PfAssert(j == Flash->sect_sz);
rc = FlashWriteCtrlSect();
if (rc)
return rc;
offset = 0;
Flash->ctrl_sect = Flash->sect_tbl[Flash->ctrl_sect].next;
}
/*-----------------------------------------------------------------*/
/* Pad the rest of the last sector with 0xFFs, except for CRC. */
/*-----------------------------------------------------------------*/
PfAssert(offset < Flash->sect_sz - 4);
for (i = offset; i < Flash->sect_sz - 4; ++i)
{
Flash->tmp_sect[i] = 0xFF;
crc = CRC_UPDATE(crc, 0xFF);
}
/*-----------------------------------------------------------------*/
/* Write the CRC. */
/*-----------------------------------------------------------------*/
for (j = 0, crc = ~crc; j < 4; ++j)
Flash->tmp_sect[i + j] = (ui8)(crc >> (8 * j));
/*-----------------------------------------------------------------*/
/* Write the buffered sector to flash. */
/*-----------------------------------------------------------------*/
rc = FlashWriteCtrlSect();
if (rc)
return rc;
}
return 0;
}
/***********************************************************************/
/* FsNandEraseBlockWrapper: Wrapper function for the NAND driver erase */
/* block */
/* */
/* Input: addr = address within block to be erased */
/* */
/* Returns: 0 on success, -1 on failure */
/* */
/***********************************************************************/
int FsNandEraseBlockWrapper(ui32 addr)
{
int status;
FlashGlob *vol;
/*-------------------------------------------------------------------*/
/* Release exclusive access to the flash file system. */
/*-------------------------------------------------------------------*/
vol = Flash;
semPost(FlashSem);
/*-------------------------------------------------------------------*/
/* Erase block. */
/*-------------------------------------------------------------------*/
status = vol->driver.nand.erase_block(addr, vol->vol);
/*-------------------------------------------------------------------*/
/* Acquire exclusive access to the flash file system. */
/*-------------------------------------------------------------------*/
semPend(FlashSem, WAIT_FOREVER);
Flash = vol;
/*-------------------------------------------------------------------*/
/* If the block erase fails, it's an invalid block. */
/*-------------------------------------------------------------------*/
if (status)
{
ui32 i, sect, first_invalid, last_invalid = (ui32)-1;
ui32 block = (addr - Flash->mem_base) / Flash->block_size;
#if FFS_DEBUG
printf("NAND: erase block %u failure!\n", block);
#endif
/*-----------------------------------------------------------------*/
/* Increment the total number of bad blocks. */
/*-----------------------------------------------------------------*/
++Flash->bad_blocks;
/*-----------------------------------------------------------------*/
/* Mark block as bad. */
/*-----------------------------------------------------------------*/
PfAssert(!Flash->blocks[block].ctrl_block);
Flash->blocks[block].bad_block = TRUE;
/*-----------------------------------------------------------------*/
/* Mark all sectors in block as invalid. */
/*-----------------------------------------------------------------*/
sect = block * Flash->block_sects;
if (Flash->sect_tbl[sect].prev == FFREE_SECT)
{
first_invalid = sect;
last_invalid = first_invalid + Flash->block_sects - 1;
Flash->free_sects -= Flash->block_sects;
PfAssert(Flash->sect_tbl[last_invalid].prev == FFREE_SECT);
}
else
first_invalid = (ui32)-1;
for (i = 0; i < Flash->block_sects; ++i, ++sect)
Flash->sect_tbl[sect].prev = FNVLD_SECT;
if (first_invalid != (ui32)-1)
{
/*---------------------------------------------------------------*/
/* Find the sector in free list that points to first invalid */
/* sector (if there is one, it is at end of a block). */
/*---------------------------------------------------------------*/
sect = Flash->block_sects - 1;
for (block = 0; block < Flash->num_blocks; ++block)
{
if (!Flash->blocks[block].bad_block)
{
if (Flash->sect_tbl[sect].prev == FFREE_SECT &&
Flash->sect_tbl[sect].next == first_invalid)
{
Flash->sect_tbl[sect].next =
Flash->sect_tbl[last_invalid].next;
if (Flash->sect_tbl[sect].next == FLAST_SECT)
Flash->last_free_sect = sect;
break;
}
}
sect += Flash->block_sects;
}
}
}
/*-------------------------------------------------------------------*/
/* If number of bad blocks has exceeded maximum, error. */
/*-------------------------------------------------------------------*/
if (Flash->bad_blocks > Flash->max_bad_blocks)
return -1;
return 0;
}
/***********************************************************************/
/* FsNandUnformatToFormat: NAND specific code to prepare unformatted */
/* volume for format */
/* */
/* Returns: 0 on success, -1 on error */
/* */
/***********************************************************************/
int FsNandUnformatToFormat(void)
{
int sect, block, i;
Flash->bad_blocks = 0;
Flash->free_sect = (ui32)-1;
Flash->free_sects = 0;
Flash->last_free_sect = (ui32)-1;
/*-------------------------------------------------------------------*/
/* Look for bad vs. free blocks. */
/*-------------------------------------------------------------------*/
for (block = 0; block < Flash->num_blocks; ++block)
{
Flash->blocks[block].used_sects = 0;
Flash->blocks[block].ctrl_block = FALSE;
Flash->blocks[block].wear_count = 0;
sect = (int)(block * Flash->block_sects);
for (i = 0; i < Flash->block_sects; ++i, ++sect)
{
/*---------------------------------------------------------------*/
/* If a sector is non-empty at this stage, its block is bad. */
/*---------------------------------------------------------------*/
if (Flash->max_bad_blocks && !FsNandEmptySect(sect))
{
Flash->blocks[block].bad_block = TRUE;
++Flash->bad_blocks;
/*-------------------------------------------------------------*/
/* Mark all sectors in block as invalid. */
/*-------------------------------------------------------------*/
sect = (int)(block * Flash->block_sects);
for (i = 0; i < Flash->block_sects; ++i, ++sect)
Flash->sect_tbl[sect].prev = FNVLD_SECT;
sect = -1;
break;
}
/*---------------------------------------------------------------*/
/* Mark sector as free. */
/*---------------------------------------------------------------*/
Flash->sect_tbl[sect].prev = FFREE_SECT;
Flash->sect_tbl[sect].next = (ui16)(sect + 1);
}
/*-----------------------------------------------------------------*/
/* If block is free, tie it in with the free list. */
/*-----------------------------------------------------------------*/
if (sect != -1)
{
Flash->free_sects += Flash->block_sects;
if (Flash->free_sect == (ui32)-1)
Flash->free_sect = block * Flash->block_sects;
else
Flash->sect_tbl[Flash->last_free_sect].next =
(ui16)(block * Flash->block_sects);
Flash->last_free_sect = (ui32)(sect - 1);
Flash->sect_tbl[Flash->last_free_sect].next = FLAST_SECT;
Flash->blocks[block].bad_block = FALSE;
}
}
return 0;
}
/***********************************************************************/
/* FsNandAddVol: Add NAND volume */
/* */
/* Input: driver = pointer to the driver control block */
/* */
/* Returns: 0 on success, -1 on error */
/* */
/***********************************************************************/
int FsNandAddVol(const FfsVol *driver)
{
return FlashAddVol(driver, FFS_NAND);
}
/***********************************************************************/
/* FsNandFindLastCtrl: Look for most recent control information */
/* */
/* Returns: First sector of most recent control information or -1 */
/* if no control information was found */
/* */
/***********************************************************************/
int FsNandFindLastCtrl(void)
{
int beg_ctrl_sect = -1, ctrl_start;
ui32 high_seq_num = 0, seq_num, sect;
/*-------------------------------------------------------------------*/
/* Scan the whole flash for valid ctrl info. Remember the one with */
/* latest sequence number. */
/*-------------------------------------------------------------------*/
for (sect = 0;;)
{
/*-----------------------------------------------------------------*/
/* Find the next valid copy of control information in flash. */
/*-----------------------------------------------------------------*/
ctrl_start = next_ctrl(§, &seq_num);
/*-----------------------------------------------------------------*/
/* If no more valid ctr info found, break. */
/*-----------------------------------------------------------------*/
if (ctrl_start == -1)
break;
/*-----------------------------------------------------------------*/
/* If this is first valid ctrl info, or it's more recent than the */
/* saved one, remember it as the most recent one. */
/*-----------------------------------------------------------------*/
if ((beg_ctrl_sect == -1) || SEQ_GT(seq_num, high_seq_num))
{
beg_ctrl_sect = ctrl_start;
high_seq_num = seq_num;
#if FFS_DEBUG
printf("high_seq_num = 0x%08X\n", high_seq_num);
#endif
}
}
/*-------------------------------------------------------------------*/
/* Return beginning ctrl sect or -1 if ctrl info not present. */
/*-------------------------------------------------------------------*/
return beg_ctrl_sect;
}
/***********************************************************************/
/* FsNandEmptySect: Check if a flash sector is empty */
/* */
/* Input: sector = sector to check */
/* */
/* Returns: TRUE if empty, FALSE otherwise */
/* */
/***********************************************************************/
int FsNandEmptySect(ui32 sector)
{
ui32 i, addr = Flash->mem_base + Flash->sect_sz * sector;
/*-------------------------------------------------------------------*/
/* Loop to check each page in the sector. */
/*-------------------------------------------------------------------*/
for (i = 0; i < Flash->pages_per_sect; ++i, addr += Flash->page_size)
{
/*-----------------------------------------------------------------*/
/* If read fails, sector is considered not empty. */
/*-----------------------------------------------------------------*/
if (!Flash->driver.nand.page_erased(addr, Flash->vol))
return FALSE;
}
return TRUE;
}
#endif /* INC_NAND_FS && NUM_FFS_VOLS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -