📄 jnand.c.bak
字号:
/*===========================================================================
FUNCTION flash_initialize_boot
DESCRIPTION
This function calls the flash probe function and sets up everything to be
ready to erase and program the device.
DEPENDENCIES
Assumes jtag_flash_param (global variable) has valid parameters.
RETURN VALUE
If success, return FLASH_SUCCESS else FLASH_FAIL
SIDE EFFECTS
===========================================================================*/
uint32
flash_initialize_boot()
{
KICK_WATCHDOG();
DPRINTF (("\n\n------ Boot Initialize ----------------------\n"));
DPRINTF (("Probing flash device: "));
nand_device=fs_nand_device_probe();
if ( nand_device == (struct fs_device_data *)FS_NO_DEVICE)
{
DPRINTF (("Error: no nand_device found \n"));
SET_ERR (ERR_DEV_MISSING);
return FLASH_FAIL;
}
/* Initialize the CRC with the seed value so we only have to
* call the step function. This must be done initialize, not
* just at compile time with an assignment on the variable
* declaration, because we call this program multiple times
* and during EACH invocation run, we must start the CRC
* over from the seed. */
crc = CRC_30_STEP_SEED;
/* get some information about the device */
block_count = nand_device->block_count(nand_device);
pages_in_block = nand_device->block_size(nand_device);
page_size = nand_device->page_size(nand_device);
flash_name = nand_device->device_name(nand_device);
/* calculate size of eraseable unit and max number of pages */
eu_size = pages_in_block * page_size;
max_pages = block_count * pages_in_block;
/* page counter later used to read back image for verification */
boot_block_pages = 0;
boot_block_mode = TRUE;
DPRINTF (("Found %s\n", flash_name));
#ifdef DEBUG_LOGIC
#error code not present
#endif
KICK_WATCHDOG();
/* Init some things that must be re-inited on every invocation. */
start_addr_loaded = FALSE;
image_size = 0;
input_gap_size = 0;
bad_block_gap_size = 0;
partial_page_index = 0;
current_block = 0;
avail_pages_in_block = 0;
current_page = 0;
KICK_WATCHDOG();
return FLASH_SUCCESS;
} // flash_initialize_boot
/*===========================================================================
FUNCTION flash_erase
DESCRIPTION
This function does nothing. It is just a stub. Since we only require
that block 0 be good, and we can work around any other bad blocks for
the Boot Information Block and the image data, there is no longer
anything to do.
DEPENDENCIES
None
RETURN VALUE
Always return FLASH_SUCCESS
SIDE EFFECTS
===========================================================================*/
uint32 flash_erase()
{
return FLASH_SUCCESS;
} // flash_erase
/*===========================================================================
FUNCTION flash_erase_boot
DESCRIPTION
This function checks the boot block only, then erases it
DEPENDENCIES
RETURN VALUE
If block 0 is good return FLASH_SUCCESS
If block 0 is bad return FLASH_FAIL
SIDE EFFECTS
===========================================================================*/
uint32 flash_erase_boot()
{
int i = 0;
DPRINTF (("\n------ ERASE BOOT -----\n"));
/* For right now, only check block 0, leaving other blocks
* alone. If this block is bad, we fail utterly */
KICK_WATCHDOG();
if (nand_device->bad_block_check(nand_device, i) ==
FS_DEVICE_BAD_BLOCK)
{
TPRINTF (0, ("flash_erase: bad block %d\n", i));
return FLASH_FAIL;
}
KICK_WATCHDOG();
/* erase the block */
if (nand_device->erase_block(nand_device, i) != FS_DEVICE_DONE)
{
DPRINTF (("Error: device failed during erase of block %d\n", i));
SET_ERR (ERR_ERASE_FAIL);
return FLASH_FAIL;
}
KICK_WATCHDOG();
/* We do this here instead of in initialize because until we have
* erased this block successfully, we have none. Now we do, and
* because we are in boot_block_mode, we will never call
* prepare_next_block() which would normally erase and init the
* first block. */
avail_pages_in_block = page_size;
return FLASH_SUCCESS;
} // flash_boot
/*===========================================================================
FUNCTION flash_program
DESCRIPTION
This function will write the flash. It gets invoked every time the
JTAG ICD has filled a buffer. Those buffer fills may not have any
correspondence to the size of the pages we can write to the flash,
so we must be prepared to partially fill a block with data on one pass
through and then continue filling the block on the next pass through.
This means that state must be maintained in globals after this function
has finished with the current invocation.
DEPENDENCIES
Assumes jtag_flash_param (global variable) has valid parameters.
RETURN VALUE
If success, return FLASH_SUCCESS else FLASH_FAIL
SIDE EFFECTS
===========================================================================*/
uint32 flash_program()
{
byte *data;
dword addr;
word size;
unsigned int fill_remaining_in_page;
unsigned int partial_bytes_avail, num_fill_bytes;
unsigned int gap_size;
unsigned int new_last_code_addr;
unsigned char *wbuf;
KICK_WATCHDOG();
// DPRINTF (("\n----- PROGRAM ------\n"));
data = jtag_flash_param.data + jtag_flash_param.offset;
addr = jtag_flash_param.addr + jtag_flash_param.offset
- jtag_flash_param.flashaddr;
size = jtag_flash_param.size;
/* Save address of last code byte so we know where the next block of
* code is in relation to it's predecessor.
*/
new_last_code_addr = addr + size;
/* If this is the first block of code, save the start address
* of the code image in the RAM copy of BIB. */
if (start_addr_loaded == FALSE)
{
start_addr_loaded = TRUE;
bib1.startaddr = addr;
last_code_addr = addr;
}
/* If there is a gap between previous last image address and the
* starting address of the current image data, fill with fill char
* and update number of fill chars used. Also, we are forced to
* use the partial page buffer if we are doing a fill. Account for
* gaps that stay within the partial page, as well as gaps that go
* beyond the partial, and possibly gaps that are larger than the
* the partial page. However, we no longer have any spans to close out,
* so we just fill with required number of fill bytes and write out
* full pages as necessary, even if they are merely full of fill bytes. */
KICK_WATCHDOG();
if (last_code_addr != addr)
{
gap_size = num_fill_bytes = addr - last_code_addr;
/* check to make sure we have not got a block with an address less
* than we have had before.
*/
if (addr < last_code_addr)
{
DPRINTF (("Error: addr to program %d < previous addr %d \n",
addr, last_code_addr));
SET_ERR (ERR_ADDR_REVERSE);
return FLASH_FAIL;
}
while (num_fill_bytes > 0)
{
partial_bytes_avail = page_size - partial_page_index;
fill_remaining_in_page = MIN (partial_bytes_avail, num_fill_bytes);
while (fill_remaining_in_page > 0)
{
partial_page_buffer[partial_page_index++] =
(unsigned char)NAND_FILL_CHAR;
num_fill_bytes--;
fill_remaining_in_page--;
}
if (partial_page_index > page_size)
{
SET_ERR (ERR_PPI_TOO_BIG);
return FLASH_FAIL;
}
if (partial_page_index == page_size)
{
KICK_WATCHDOG();
if ((write_partial_page (addr, UPDATE_CRC)) == FALSE)
{
return FLASH_FAIL;
}
partial_page_index = 0;
} /* partial page is full */
} /* while */
input_gap_size += gap_size;
} /* there is a gap in code addresses */
KICK_WATCHDOG();
/* Now write the data */
while (size > 0)
{
partial_bytes_avail = page_size - partial_page_index;
if (partial_bytes_avail > size)
{
/* fill partial page partially and we are done, do not write page,
* no need to update data ptr as we are out of data */
memcpy(&partial_page_buffer[partial_page_index], data, size);
partial_page_index += size;
break;
}
else if ((partial_bytes_avail == size) && (partial_page_index != 0))
{
/* fill partial page completely, ready for writing, none left over */
memcpy(&partial_page_buffer[partial_page_index], data, size);
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
/*===========================================================================
FUNCTION flash_program_boot
DESCRIPTION
This function will write the flash. It gets invoked every time the
JTAG ICD has filled a buffer. Those buffer fills may not have any
correspondence to the size of the pages we can write to the flash,
so we must be prepared to partially fill a block with data on one pass
through and then continue filling the block on the next pass through.
This means that state must be maintained in globals after this function
has finished with the current invocation.
DEPENDENCIES
Assumes jtag_flash_param (global variable) has valid parameters.
RETURN VALUE
If success, return FLASH_SUCCESS else FLASH_FAIL
SIDE EFFECTS
===========================================================================*/
uint32 flash_program_boot()
{
byte *data;
dword addr;
word size;
unsigned int partial_bytes_avail, num_fill_bytes, fill_remaining_in_page;
unsigned int gap_size;
unsigned int new_last_code_addr;
unsigned char *wbuf;
KICK_WATCHDOG();
DPRINTF (("\n----- PROGRAM BOOT BLOCK------\n"));
data = jtag_flash_param.data + jtag_flash_param.offset;
addr = jtag_flash_param.addr + jtag_flash_param.offset
- jtag_flash_param.flashaddr;
size = jtag_flash_param.size;
/* Save address of last code byte so we know where the next block of
* code is in relation to it's predecessor.
*/
new_last_code_addr = addr + size;
/* If this is the first block of code, save the start address
* of the code image */
if (start_addr_loaded == FALSE)
{
start_addr_loaded = TRUE;
last_code_addr = addr;
}
/* If there is a gap between previous last image address and the
* starting address of the current image data, fill with fill char
* and update number of fill chars used. Also, we are forced to
* use the partial page buffer if we are doing a fill. Account for
* gaps that stay within the partial page, as well as gaps that go
* beyond the partial, and possibly gaps that are larger than the
* the partial page. However, as opposed to regular programming
* mode, we do not have any spans to close out, so we just
* fill with required number of fill bytes and write out full pages
* as necessary, even if they are merely full of fill bytes. */
KICK_WATCHDOG();
if (last_code_addr != addr)
{
gap_size = num_fill_bytes = addr - last_code_addr;
/* check to make sure we have not got a block with an address less
* than we have had before.
*/
if (addr < last_code_addr)
{
DPRINTF (("Error: addr to program %d < previous addr %d \n",
addr, last_code_addr));
SET_ERR (ERR_ADDR_REVERSE);
return FLASH_FAIL;
}
while (num_fill_bytes > 0)
{
partial_bytes_avail = page_size - partial_page_index;
fill_remaining_in_page = MIN (partial_bytes_avail, num_fill_bytes);
while (fill_remaining_in_page > 0)
{
partial_page_buffer[partial_page_index++] =
(unsigned char)NAND_FILL_CHAR;
num_fill_bytes--;
fill_remaining_in_page--;
}
if (partial_page_index > page_size)
{
SET_ERR (ERR_PPI_TOO_BIG);
return FLASH_FAIL;
}
if (partial_page_index == page_size)
{
KICK_WATCHDOG();
if ((write_partial_page (addr, UPDATE_CRC)) == FALSE)
{
return FLASH_FAIL;
}
partial_page_index = 0;
} /* partial page is full */
} /* while */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -