📄 nand_util.c
字号:
/*-----------------------------------------------------------------*/
if (status == -1)
{
bad_block = sect_num / Flash->block_sects;
/*---------------------------------------------------------------*/
/* If part of current control info in this block, invalidate it. */
/*---------------------------------------------------------------*/
if (Flash->frst_ctrl_sect / Flash->block_sects == bad_block)
{
frst_ctrl_sect = Flash->frst_ctrl_sect;
/*-------------------------------------------------------------*/
/* Invalidate all the control sectors. */
/*-------------------------------------------------------------*/
if (frst_ctrl_sect != (ui32)-1)
{
/*-----------------------------------------------------------*/
/* Invalidate a block at a time. */
/*-----------------------------------------------------------*/
for (j = frst_ctrl_sect; j != FLAST_SECT;)
{
/*---------------------------------------------------------*/
/* Invalidate control block. */
/*---------------------------------------------------------*/
do
{
Flash->sect_tbl[i = j].prev = FDRTY_SECT;
j = Flash->sect_tbl[j].next;
} while (j != FLAST_SECT && (i + 1) % Flash->block_sects);
/*---------------------------------------------------------*/
/* Unmark control block flag. */
/*---------------------------------------------------------*/
Flash->blocks[i / Flash->block_sects].ctrl_block = FALSE;
}
}
/*-------------------------------------------------------------*/
/* If free control area in bad block, invalidate it. */
/*-------------------------------------------------------------*/
if (Flash->free_ctrl_sect / Flash->block_sects == bad_block)
Flash->free_ctrl_sect = (ui32)-1;
}
/*---------------------------------------------------------------*/
/* Mark block as bad. */
/*---------------------------------------------------------------*/
return mark_block_bad(sect_num);
}
}
return 0;
}
/***********************************************************************/
/* FsNandWriteSect: Write a given sector to flash by calling driver */
/* write routine */
/* */
/* Inputs: buffer = pointer to buffer containing sector data */
/* sect_num = the sector number */
/* sect_type = sector type (data or control) */
/* */
/* Returns: 0 on success, -1 on failure, RWR_CTRL_OK if control */
/* was rewritten succesfully */
/* */
/***********************************************************************/
int FsNandWriteSect(void *buffer, ui32 sect_num, ui32 sect_type)
{
int i, status;
ui32 addr = Flash->mem_base + sect_num * Flash->sect_sz;
ui32 wear = Flash->blocks[sect_num / Flash->block_sects].wear_count;
ui32 next_sect_num, bad_block = sect_num / Flash->block_sects;
void *orig_buffer = buffer;
FlashGlob *vol;
/*-------------------------------------------------------------------*/
/* Write sector to flash, 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 page. */
/*-----------------------------------------------------------------*/
status = vol->driver.nand.write_page(buffer, addr, (ui32)sect_type,
wear, vol->vol);
/*-----------------------------------------------------------------*/
/* Acquire exclusive access to the flash file system. */
/*-----------------------------------------------------------------*/
semPend(FlashSem, WAIT_FOREVER);
Flash = vol;
/*-----------------------------------------------------------------*/
/* If write error, either program disturb or bad block. */
/*-----------------------------------------------------------------*/
if (status)
{
/*---------------------------------------------------------------*/
/* Data sector. */
/*---------------------------------------------------------------*/
if (sect_type == DATA_SECT)
{
/*-------------------------------------------------------------*/
/* If bad, block, mark it. */
/*-------------------------------------------------------------*/
if (status == -1 && mark_block_bad(bad_block))
return -1;
/*-------------------------------------------------------------*/
/* Relocate bad sector. */
/*-------------------------------------------------------------*/
if (FlashRelocSect(sect_num, Flash->free_sect, orig_buffer))
return -1;
/*-------------------------------------------------------------*/
/* If bad block, invalidate sector that was just relocated. */
/*-------------------------------------------------------------*/
if (status == -1)
Flash->sect_tbl[sect_num].prev = FNVLD_SECT;
return 0;
}
/*---------------------------------------------------------------*/
/* Control sector. */
/*---------------------------------------------------------------*/
else
{
/*-------------------------------------------------------------*/
/* All control sectors up to and including current one become */
/* dirty. */
/*-------------------------------------------------------------*/
next_sect_num = invalidate_ctrl_sects_upto(sect_num);
/*-------------------------------------------------------------*/
/* If bad block, control sectors in current block become dirty.*/
/*-------------------------------------------------------------*/
if (status == -1)
{
/*-----------------------------------------------------------*/
/* Mark all sectors in current block as dirty. */
/*-----------------------------------------------------------*/
sect_num = bad_block * Flash->block_sects;
for (i = 0; i < Flash->block_sects; ++i, ++sect_num)
Flash->sect_tbl[sect_num].prev = FDRTY_SECT;
/*-----------------------------------------------------------*/
/* Mark block bad. */
/*-----------------------------------------------------------*/
if (mark_block_bad(bad_block))
return -1;
/*-----------------------------------------------------------*/
/* Also, invalidate first free control sector. */
/*-----------------------------------------------------------*/
Flash->free_ctrl_sect = (ui32)-1;
}
/*-------------------------------------------------------------*/
/* Else, invalidate all sectors in current block and the free */
/* control sector. */
/*-------------------------------------------------------------*/
else
{
++sect_num;
Flash->free_ctrl_sect = (ui32)-1;
for (; sect_num % Flash->block_sects; ++sect_num)
Flash->sect_tbl[sect_num].prev = FDRTY_SECT;
}
/*-------------------------------------------------------------*/
/* All control blocks past current one become free. */
/*-------------------------------------------------------------*/
free_ctrl_blocks_from(next_sect_num);
/*-------------------------------------------------------------*/
/* No more valid control information left. */
/*-------------------------------------------------------------*/
Flash->frst_ctrl_sect = Flash->last_ctrl_sect = (ui32)-1;
/*-------------------------------------------------------------*/
/* Rewrite the control information. */
/*-------------------------------------------------------------*/
if (FlashWrCtrl(SKIP_ADJUST_ERASE))
return -1;
else
return RWR_CTRL_OK;
}
}
buffer = (ui8 *)buffer + Flash->page_size;
}
return 0;
}
/***********************************************************************/
/* FsNandWriteCtrl: Write a chunk of control memory to NAND */
/* */
/* Inputs: head = pointer to the beginning of chunk in RAM */
/* length = number of bytes the chunk has */
/* */
/* Returns: 0 on success, -1 on failure, RWR_CTRL_OK in case the */
/* whole ctrl was rewritten because of bad block */
/* */
/***********************************************************************/
int FsNandWriteCtrl(const void *head, uint length)
{
int i = 0, j, rc;
ui32 next_block;
static ui32 crc;
static int offset;
static ui32 tot_sects;
/*-------------------------------------------------------------------*/
/* Check if this call is just to initialize the static variables. */
/*-------------------------------------------------------------------*/
if (head == Flash)
{
tot_sects = Flash->ctrl_sects;
crc = CRC32_START;
offset = 0;
return 0;
}
/*-------------------------------------------------------------------*/
/* Copy data from head to buffer, and as soon as 1 sector in the */
/* buffer gets filled, write it to flash. */
/*-------------------------------------------------------------------*/
while (i < length)
{
/*-----------------------------------------------------------------*/
/* If a full sector worth of ctrl data has been written to buffer, */
/* send it to flash. */
/*-----------------------------------------------------------------*/
PfAssert(offset <= Flash->sect_sz);
if (offset == Flash->sect_sz)
{
/*---------------------------------------------------------------*/
/* Write the TmpBuf.data to flash. */
/*---------------------------------------------------------------*/
rc = FlashWriteCtrlSect();
if (rc)
return rc;
/*---------------------------------------------------------------*/
/* Update the state variables. */
/*---------------------------------------------------------------*/
Flash->ctrl_sect = Flash->sect_tbl[Flash->ctrl_sect].next;
--tot_sects;
offset = 0;
}
/*-----------------------------------------------------------------*/
/* If this is the last sector in a block and we are down to the */
/* last two bytes, write the next ctrl block. */
/*-----------------------------------------------------------------*/
if (offset == Flash->sect_sz - 2 &&
(Flash->ctrl_sect + 1) % Flash->block_sects == 0)
{
next_block = Flash->sect_tbl[Flash->ctrl_sect].next /
Flash->block_sects;
Flash->tmp_sect[offset++] = (ui8)((next_block & 0xFF00) >> 8);
Flash->tmp_sect[offset++] = (ui8)(next_block & 0xFF);
crc = CRC_UPDATE(crc, Flash->tmp_sect[offset - 2]);
crc = CRC_UPDATE(crc, Flash->tmp_sect[offset - 1]);
}
else
{
/*---------------------------------------------------------------*/
/* Copy one byte at a time from head into buffer. */
/*---------------------------------------------------------------*/
Flash->tmp_sect[offset++] = ((ui8 *)head)[i];
/*---------------------------------------------------------------*/
/* Update the CRC with the new ctrl info byte. */
/*---------------------------------------------------------------*/
crc = CRC_UPDATE(crc, ((ui8 *)head)[i++]);
}
}
/*-------------------------------------------------------------------*/
/* If it's last write, add the CRC at the end of the ctrl info. */
/*-------------------------------------------------------------------*/
if (length == 0)
{
/*-----------------------------------------------------------------*/
/* Fill out the rest of ctrl sectors with 0xFF, except for last */
/* ctrl sector. */
/*-----------------------------------------------------------------*/
PfAssert(tot_sects > 0);
for (; tot_sects > 1; --tot_sects)
{
for (j = offset; j < Flash->sect_sz - 2; ++j)
{
Flash->tmp_sect[j] = 0xFF;
crc = CRC_UPDATE(crc, 0xFF);
}
/*---------------------------------------------------------------*/
/* If on block boundary, save next block in last two bytes, else */
/* use 0xFF. */
/*---------------------------------------------------------------*/
if ((Flash->ctrl_sect + 1) % Flash->block_sects == 0)
{
next_block = Flash->sect_tbl[Flash->ctrl_sect].next /
Flash->block_sects;
Flash->tmp_sect[j++] = (ui8)((next_block & 0xFF00) >> 8);
Flash->tmp_sect[j++] = (ui8)(next_block & 0xFF);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -