📄 jnand.c
字号:
wbuf = partial_page_buffer;
data += partial_bytes_avail;
size -= partial_bytes_avail;
partial_page_index = 0;
}
else if ((partial_bytes_avail < size) && (partial_page_index != 0))
{
/* fill partial page completely, ready for writing, some left over */
memcpy(&partial_page_buffer[partial_page_index], data, partial_bytes_avail);
wbuf = partial_page_buffer;
data += partial_bytes_avail;
size -= partial_bytes_avail;
partial_page_index = 0;
}
else /* partial_page_index == 0 && size >= page_size */
{
/* write a full page from where it is */
wbuf = data;
data += page_size;
size -= page_size;
}
KICK_WATCHDOG();
/* Write a full page. If we do not break out of the while early,
* and we reach here, there is a full page to be written. */
if (write_current_page (wbuf, addr, UPDATE_CRC) == FALSE)
{
return FLASH_FAIL;
}
KICK_WATCHDOG();
/* We only get here when we have a full page to write, so the
* increment of the address in the code image is always by a page. */
addr += page_size;
}
/* Save the RAM address of the last byte of the image written, so
* that when we get called next, we can see if there are any gaps */
last_code_addr = new_last_code_addr;
if (partial_page_index > page_size)
{
return FLASH_FAIL;
}
return FLASH_SUCCESS;
} // flash_program_boot
/*===========================================================================
FUNCTION flash_finalize
DESCRIPTION
This function will write any remaining data that is still buffered.
It will then write the BIB including checksum.
DEPENDENCIES
Assumes jtag_flash_param (global variable) has valid parameters.
RETURN VALUE
If success, return FLASH_SUCCESS else FLASH_FAIL
SIDE EFFECTS
===========================================================================*/
uint32 flash_finalize()
{
unsigned int num_fill_bytes;
unsigned char *dst;
int spans_remaining;
int total_len;
int bib_size;
KICK_WATCHDOG();
DPRINTF (("\n----- FINALIZE ------\n"));
/* Maybe fill last page of code with fill character and write the
* page. Don't include these fill bytes in total fill bytes used
* as that is keeping track only of wasted bytes internal
* to the image. */
if (partial_page_index > 0)
{
num_fill_bytes = page_size - partial_page_index;
while (num_fill_bytes > 0)
{
partial_page_buffer[partial_page_index++] =
(unsigned char)NAND_FILL_CHAR;
num_fill_bytes--;
}
if ((write_partial_page ((dword)0, UPDATE_CRC) == FALSE))
{
return FLASH_FAIL;
}
}
KICK_WATCHDOG();
/* Erase and do housekeeping for writing BIB block */
if (prepare_bib_block() == FALSE)
{
return FLASH_FAIL;
}
KICK_WATCHDOG();
DPRINTF (("finalize:Putting crc 0x%08X into BIB\n", (unsigned int)crc));
/* Fill and write the BIB. */
bib1.crc = crc;
bib1.length = image_size;
bib_size = sizeof(struct boot_info_block);
dst = partial_page_buffer;
memcpy (dst, &bib1, bib_size);
KICK_WATCHDOG();
/* Fill the first page with the Boot Information Block and fill remainder
* of page with fill char */
total_len = bib_size;
dst += bib_size;
num_fill_bytes = page_size - total_len;
while (num_fill_bytes > 0)
{
*dst++ = (unsigned char)NAND_FILL_CHAR;
num_fill_bytes--;
}
KICK_WATCHDOG();
if (write_current_page ((unsigned char *)partial_page_buffer,
(dword)0, NO_UPDATE_CRC) == FALSE)
{
return FLASH_FAIL;
}
spans_remaining = 0;
#ifdef DEBUG_LOGIC
#error code not present
#endif
return FLASH_SUCCESS;
} // flash_finalize
/*===========================================================================
FUNCTION flash_finalize_boot
DESCRIPTION
This function will write any remaining data that is still buffered and
enough extra pages to exactly fill the 8K boot block. If all 8K of the
boot block is not written, we will get an ECC error on read.
DEPENDENCIES
Assumes jtag_flash_param (global variable) has valid parameters.
RETURN VALUE
If success, return FLASH_SUCCESS else FLASH_FAIL
SIDE EFFECTS
===========================================================================*/
uint32
flash_finalize_boot()
{
unsigned int num_fill_bytes;
int i, j;
KICK_WATCHDOG();
DPRINTF (("\n----- BOOT FINALIZE ------\n"));
/* DPRINTF (("1:Putting crc 0x%08X into BIB\n", (unsigned int)crc)); */
if (partial_page_index > page_size)
{
return FLASH_FAIL;
}
/* Maybe fill last page of code with fill character and write the
* page. Don't include these fill bytes in total fill bytes used
* as that is keeping track only of wasted bytes internal
* to the image. */
if (partial_page_index > 0)
{
num_fill_bytes = page_size - partial_page_index;
while (num_fill_bytes > 0)
{
partial_page_buffer[partial_page_index++] =
(unsigned char)NAND_FILL_CHAR;
num_fill_bytes--;
}
KICK_WATCHDOG();
if ((write_partial_page ((dword)0, UPDATE_CRC) == FALSE))
{
return FLASH_FAIL;
}
}
/* Fill rest of 8k of pages (16 pages) with 0x00 and write */
for (i=boot_block_pages; i<16; i++)
{
for (j=0; j<page_size; j++)
{
partial_page_buffer[j] = (unsigned char)0;
}
KICK_WATCHDOG();
if ((write_partial_page ((dword)0, UPDATE_CRC) == FALSE))
{
return FLASH_FAIL;
}
}
KICK_WATCHDOG();
return FLASH_SUCCESS;
} // flash_finalize_boot
/*===========================================================================
FUNCTION prepare_next_block
DESCRIPTION
This function will erase the next available non-bad block in the flash
and update all global variables to point to it and its pages as the
next available for use. It will also close the current span and open the
next available span if any bad block was encountered.
DEPENDENCIES
None
RETURN VALUE
If success, return TRUE else FALSE
SIDE EFFECTS
===========================================================================*/
int
prepare_next_block (dword addr)
{
int result;
/* Advance to next non-bad block */
while (nand_device->bad_block_check(nand_device, ++current_block) ==
FS_DEVICE_BAD_BLOCK)
{
TPRINTF (2, ("pnb: skipping block %d \n", (current_block - 1)));
bad_block_gap_size += eu_size;
}
/* Make sure we did not go past the end of the flash */
if (current_block >= block_count)
{
DPRINTF (("Error: Attempted to program beyond end of device\n"));
SET_ERR (ERR_PAST_NAND_END);
return FALSE;
}
TPRINTF (3, ("pnb: erasing block 0x%x\n", current_block));
/* erase the block */
result=nand_device->erase_block( nand_device, current_block );
if ( result != FS_DEVICE_DONE )
{
DPRINTF (("Error: device failed during erase\n"));
SET_ERR (ERR_ERASE_FAIL);
return FALSE;
}
/* do housekeeping to set up to use block just erased */
current_page = current_block * pages_in_block;
avail_pages_in_block = pages_in_block;
TPRINTF (3, ("pnb: new block at 0x%x\n", current_block));
return TRUE;
}
/*===========================================================================
FUNCTION prepare_first_block
DESCRIPTION
This function will erase the first available non-bad block in the flash
past the Boot Information Block and update all global variables to point
to it and its pages as the next available for use.
It is called once at init time with current block pointing one block
past the BIB block.
DEPENDENCIES
None
RETURN VALUE
If success, return TRUE else FALSE
SIDE EFFECTS
===========================================================================*/
int
prepare_first_block (void)
{
int result;
/* Advance to next non-bad block */
while (nand_device->bad_block_check(nand_device, current_block) ==
FS_DEVICE_BAD_BLOCK)
{
TPRINTF (1, ("pfb: skipping block %d \n", current_block));
bad_block_gap_size += eu_size;
current_block++;
}
/* Make sure we did not go past the end of the flash */
if (current_block >= block_count)
{
DPRINTF (("Error: Attempted to program beyond end of device\n"));
SET_ERR (ERR_PAST_NAND_END);
return FALSE;
}
/* erase the block */
result=nand_device->erase_block( nand_device, current_block );
if ( result != FS_DEVICE_DONE )
{
DPRINTF (("Error: device failed during erase\n"));
SET_ERR (ERR_ERASE_FAIL);
return FALSE;
}
/* do housekeeping to set up to use block just erased */
current_page = current_block * pages_in_block;
avail_pages_in_block = pages_in_block;
return TRUE;
}
/*===========================================================================
FUNCTION prepare_bib_block
DESCRIPTION
This function will erase the block that will contain the BIB
and update all global variables to point to it and its pages as the
next available for use.
DEPENDENCIES
None
RETURN VALUE
If success, return TRUE else FALSE
SIDE EFFECTS
===========================================================================*/
int
prepare_bib_block (void)
{
int result;
/* Check and erase block that contains BIB */
current_block = bib_block;
result = nand_device->bad_block_check(nand_device, current_block);
if (result != FS_DEVICE_OK)
{
DPRINTF (("Error: BIB block is bad\n"));
SET_ERR (ERR_BIB_BAD);
return FALSE;
}
/* erase the block */
result=nand_device->erase_block(nand_device, current_block);
if (result != FS_DEVICE_DONE)
{
DPRINTF (("Error: device failed during erase\n"));
SET_ERR (ERR_ERASE_FAIL);
return FALSE;
}
/* do housekeeping to set up to use block just erased */
current_page = current_block * pages_in_block;
avail_pages_in_block = pages_in_block;
return TRUE;
}
/*===========================================================================
FUNCTION write_partial_page
DESCRIPTION
This function will write the currently full partial page out and
update any housekeeping variables as necessary
DEPENDENCIES
None
RETURN VALUE
If success, return TRUE else FALSE
SIDE EFFECTS
===========================================================================*/
int
write_partial_page (dword addr, int update_crc)
{
if ( (write_current_page ((unsigned char *)partial_page_buffer,
addr, update_crc) == FALSE) )
{
return FALSE;
}
partial_page_index = 0;
return TRUE;
}
/*===========================================================================
FUNCTION write_current_page
DESCRIPTION
This function will write the current page out and update any housekeeping
variables as necessary.
The parameter "addr" is used in a strange way. It is only passed on to
prepare_next_block so that if prepare_next_block has to skip a bad block,
it can initialize the next span after closing out the current span.
DEPENDENCIES
None
RETURN VALUE
If success, return TRUE else FALSE
SIDE EFFECTS
===========================================================================*/
int
write_current_page (unsigned char *src, dword addr, int update_crc)
{
int i;
unsigned char *vsrc1, *vsrc2;
unsigned char *origsrc = src;
/* If the previous write used the last page in NAND, we should fail here.
* However, this will probably be caught earlier, as once we write
* the last page, we will then try to erase the next block of pages
* and that should fail before we ever get here. Just being extra safe. */
if (current_page > max_pages)
{
DPRINTF (("Error: Write beyond end of NAND flash\n"));
SET_ERR (ERR_PAST_NAND_END);
return FALSE;
}
/* If we have no pages available, erase the next block of pages,
* skipping any bad blocks and failing if we have an erase failure
* on a supposedly good block, or if we run out of blocks. */
if (avail_pages_in_block == 0)
{
/* if we are programming the boot block and run out of pages in the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -