📄 jnand.c.bak
字号:
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
Flash Programming Plug-In for Lauterbach JTAG/ICD TRACE32
GENERAL DESCRIPTION
This program is essentially a plug-in for Lauterbach JTAG ICD TRACE32
Debugger FLASH command. The programming can be achieved in two different
modes: emulator controlled or target controlled. The emulator controlled
programming needs no program running on the target, but is slow
(typically about 1 to 5 KBytes/sec). The target controlled programming
requires a user designed FLASH programming routine (and hence this plug-in)
to be available on the target. This plug-in is called by TRACE32 with
appropriate parameters to program FLASH devices. The advantage of this
method is the higher programming speed and more flexibility in the
implementation of the programming algorithm.
To use the plug-in, see the PRACTICE file JNAND.CMM. It not only uses
the built-in FLASH.* commands, but also pokes the parameter buffer with
extended command codes that we need in order to do initialization and
finalization.
In order for the Debugger to get control back after the plug-in completes,
a breakpoint is assumed to be in place after the last instruction
executed in the plug-in.
Also, this module is used as part of the NAND flash programming layer
which is used by ARMPRG top layer.
EXTERNALIZED FUNCTIONS
If compiled for JNAND, void main_c(void)
If compiled for NANDPRG, void NAND_dispatch(void)
INITIALIZATION AND SEQUENCING REQUIREMENTS
Must place a breakpoint right after the last instruction in the plug-in
in order for the Debugger to get back control. If necessary because
it is being used in that context, the breakpoint is in the caller, not
in this function. The breakpoint is executed after the return from the
main function here.
Depending on mode, either flash_initialize() or flash_initialize_boot()
must be called before any other functions.
NOTE
This module requires that all blocks of data to be programmed be sent
in strictly increasing address order. When compiled into JNAND, the
Trace32 JTAG ICD guarantees this. When compiled into NANDPRG, there needs
to be a layer right above this layer that handles buffering for any out
of order packets due to dropped packets in transport layer.
That layer must pass data to this layer in strictly increasing address
order.
Copyright (c) 2002 by QUALCOMM Incorporated. All Rights Reserved.
*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
/*===========================================================================
EDIT HISTORY FOR MODULE
This section contains comments describing changes made to the module.
Notice that changes are listed in reverse chronological order.
$Header: //depot/asic/MSMSHARED/tools/jnand/jnand.c#5 $ $DateTime: 2004/02/26 14:43:26 $ $Author: dionh $
when who what, where, why
-------- --- ----------------------------------------------------------
02/26/04 drh Add support for erasing entire NAND flash
03/04/03 drh Changes for new boot method.
03/03/03 drh Init calc_crc with SEED in verify_boot_block
02/12/03 drh Fix bug when bad block encountered.
12/01/02 drh Remove unused variable to fix compiler warning
09/25/02 drh Taken from JNAND and used in NANDPRG - initial version
07/12/02 drh Added code to program boot block in a very different mode
from programming DMSS image.
Added code to leave debug "cookies" in RAM since we cannot
reasonably debug while in non-test mode.
07/09/02 drh Added KICK_WATCHDOG macro invocations.
07/05/02 drh Created.
===========================================================================*/
/*===========================================================================
INCLUDE FILES FOR MODULE
===========================================================================*/
#include "jnand.h"
#ifdef BUILD_JNAND
#include "jnand_msm.h"
#include "jnand_debug.h"
#else
#include "ap_msm.h"
#endif
/*===========================================================================
DEFINITIONS
===========================================================================*/
/* Forward Reference Function Prototypes */
extern int prepare_first_block (void);
extern int prepare_next_block (dword addr);
extern int prepare_bib_block (void);
extern int write_current_page (unsigned char *src, dword addrr, int update_crc);
extern int write_partial_page (dword addrr, int update_crc);
extern int flash_erase_chip (void);
#ifdef DEBUG_DUMP
#error code not present
#endif
/*===========================================================================
GLOBAL DATA
===========================================================================*/
#ifdef BUILD_JNAND
/* If building NANDPRG, ap_armprg.c contains the stack */
dword svc_stack[0x1000/4]; // main stack
#endif
/* Many variables need to be global because of the nature of how
* the JTAG ICD works. Since it executes this program over and over,
* once for each chunk of data to be written, we cannot keep state from
* call to call anywhere except in globals. */
/* Buffer to store data to write in. Generally only used on blocks
* which span successive invocations. */
unsigned char partial_page_buffer[MAX_PAGE_SIZE];
unsigned int partial_page_index = 0;
/* buffer to store readback data in for read after write compare */
unsigned char readback_buffer[MAX_PAGE_SIZE];
/* places to keep track of current page and block available */
page_id current_page;
block_id current_block;
unsigned int avail_pages_in_block = 0;
/* Place to keep track of which block the BIB goes in */
block_id bib_block;
/* keep track of addresses in code image */
unsigned int last_code_addr;
unsigned int start_addr_loaded = FALSE;
unsigned int code_length;
/* NAND device structure */
struct fs_device_data * nand_device = (struct fs_device_data *)FS_NO_DEVICE;
/* NAND device parameters */
int block_count; /* number of erasable units in flash */
int pages_in_block; /* number of pages in block */
int page_size; /* number of bytes in a page */
int eu_size; /* eraseable unit size */
int max_pages; /* number of pages in the device */
char *flash_name;
/* RAM copy in which to build boot info block contents */
struct boot_info_block bib1;
unsigned char span_rb_buf[512];
unsigned char image_rb_buf[512];
unsigned int calc_crc;
/* Some info saved away to let us intelligently decide whether we
* are wasting too much space on empty flash due to gaps in input
* data or bad blocks.
*/
int input_gap_size = 0;
int bad_block_gap_size = 0;
int image_size = 0;
/* CRC related variables. We are using a 30 bit CRC from DMSS code */
dword crc;
dword save_crc;
/* Pointer to overlay on the param block a separate definition of the data */
struct type_jtag_report *report_ptr;
/* For boot block programming mode */
int boot_block_mode = FALSE;
int boot_block_pages = 0;
/*===========================================================================
FUNCTIONS
===========================================================================*/
/*===========================================================================
FUNCTION main_c
DESCRIPTION
This function calls the appropriate routine based on what TRACE32 told us.
We have added our own additional "INITIALIZE" and "FINALIZE" and those are
handled in the JTAG CMM script manually (i.e. there is not any
flash.initialize or flash.finalize command in Trace32). We stuff the
parameter block, set the PC to the beginning of our program and go.
If this is built into NANDPRG, the parameter buffer has been stuffed
in the flash layer, not by Trace32.
DEPENDENCIES
Assumes jtag_flash_param (global variable) has valid parameters.
RETURN VALUE
None.
SIDE EFFECTS
===========================================================================*/
#ifdef BUILD_JNAND
void main_c(void)
#else
void NAND_dispatch(void)
#endif
{
uint32 ret_code = 0;
DPRINTF("In main \n");
switch ( jtag_flash_param.status )
{
case FLASH_INITIALIZE:
ret_code = flash_initialize();
break;
case FLASH_INIT_BOOT:
ret_code = flash_initialize_boot();
break;
case FLASH_ERASE:
case FLASH_ERASE5:
/*
* Accept both 2 and 5 since Lauterbach JTAG sometimes passes
* 2 and sometimes passes 5 to indicate erase, depending
* on revision of Lauterbach software.
*/
if (boot_block_mode == FALSE)
{
ret_code = flash_erase();
}
else
{
ret_code = flash_erase_boot();
}
break;
case FLASH_PROGRAM:
if (boot_block_mode == FALSE)
{
ret_code = flash_program();
}
else
{
ret_code = flash_program_boot();
}
break;
case FLASH_FINALIZE:
if (boot_block_mode == FALSE)
{
ret_code = flash_finalize();
}
else
{
ret_code = flash_finalize_boot();
}
save_crc = crc;
jtag_flash_param.reserved = (uint32)crc;
break;
#ifdef SELF_TEST
#error code not present
#endif
case FLASH_REPORT:
ret_code = flash_report();
break;
case FLASH_VERIFY:
if (boot_block_mode == FALSE)
{
ret_code = verify_boot_info();
}
else
{
ret_code = verify_boot_block(save_crc, boot_block_pages);
}
break;
case FLASH_ERASE_CHIP:
ret_code = flash_erase_chip();
break;
default:
ret_code = FLASH_FAIL;
break;
}
/* Return error code back to TRACE32, 0 = success, 0x100 = fail
* We have also stuffed our own error code in param.reserved
* so that it is easier to debug what exactly went wrong */
jtag_flash_param.status = ret_code;
} // main_c
/*===========================================================================
FUNCTION flash_initialize
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()
{
/*
* Create variable and have it reference the global release info.
* This way space for the info is created in the memory and we
* can access the value of it from the HEX file.
* This local strings should be short, as we only need the reference,
* it does not matter that we copy the whole string
*/
volatile char armprg_id_blk[] = "DUMMY";
memcpy((void*) id_tbl[0], (void*) armprg_id_blk,sizeof(armprg_id_blk));
KICK_WATCHDOG();
DPRINTF (("\n\n------ Initialize ----------------------\n"));
DPRINTF (("Probing flash device: "));
boot_block_mode = FALSE;
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;
DPRINTF (("Found %s\n", flash_name));
#ifdef DEBUG_LOGIC
#error code not present
#endif
#ifdef DEBUG_LOGIC
#error code not present
#endif /* DEBUG_LOGIC */
KICK_WATCHDOG();
/* Init some things that must be re-inited on every invocation.
* Do this before calling prepare_fiest_block() because bad_block_gap_size
* may be updated in that function */
start_addr_loaded = FALSE;
image_size = 0;
input_gap_size = 0;
bad_block_gap_size = 0;
partial_page_index = 0;
/* VERY IMPORTANT: Since we have not yet erased any block, we
* must set avail_pages_in_block to zero. In this manner, when we
* go to write the block for the first time, we will have no pages
* available and we will erase the block and only then will we
* have pages available. Setting it to zero will be the trigger
* for the FIRST erase.
*/
avail_pages_in_block = 0;
/* Set up to point to the first available page in the first available
* block for Boot Info Block. (first available block times pages per block).
*
* Also set up to point to the first available block for the BIB.
*
* The algorithm we use is the Boot Information Block goes in the first
* non-bad block past block 0. The first block of image data is the
* second non-bad-block past block 0.
*
* Since at the first invocation, there are no pages available in the
* "current block", we need to do a special preparation of the first
* block that is basically the same as prepare_next_block() except
* that it does not update any spans. The call to prepare_first_block()
* will update avail_pages_in_block, which we otherwise would have to
* do here.
*/
/* Find first non-bad block past block 0 for BIB */
bib_block = FIRST_POSSIBLE_BLOCK;
while (nand_device->bad_block_check(nand_device, bib_block) ==
FS_DEVICE_BAD_BLOCK)
{
bib_block++;
}
TPRINTF (2, ("flash_initialize: bib block at 0x%x\n", bib_block));
KICK_WATCHDOG();
/* Find first non-bad block past BIB for image data. We set
* current_block to point one past the BIB, because prepare_first_block
* tests for bad blocks starting at current_block, advancing until
* it finds the first non-bad block, which may be this block. */
current_block = bib_block + 1;
if (prepare_first_block () == FALSE)
{
return FLASH_FAIL;
}
TPRINTF (2, ("flash_initialize: first data block at 0x%x\n",
current_block));
KICK_WATCHDOG();
/* init image of Boot Information Block with static data */
bib1.magic1 = MAGIC1;
bib1.magic2 = MAGIC2;
bib1.version = BIB_VERSION;
return FLASH_SUCCESS;
} // flash_initialize
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -