⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jnand.c.bak

📁 QUALCOMM JNAND DRIVER
💻 BAK
📖 第 1 页 / 共 4 页
字号:
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*

          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 + -