jnand_testnand.c

来自「QUALCOMM JNAND DRIVER」· C语言 代码 · 共 372 行

C
372
字号
/**********************************************************************
 * jnand_testnand.c
 *
 * Tests run to test the NAND device driver layer
 *
 *
 * Copyright (C) 2002, Qualcomm, Inc.
 *
 **********************************************************************/

/*===========================================================================

                        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_testnand.c#3 $ $DateTime: 2003/08/29 14:06:58 $ $Author: dionh $

when         who     what, where, why
--------     ---     ----------------------------------------------------------
2003-08-29   drh     Add KICK_WATCHDOG liberally throughout.
                     Add new test that will only check and inform of bad
                     block status.
2003-08-27   drh     Taken from EFS2 test framework to become part of JNAND
                     so that we do not have to test device drivers as part of
                     DMSS, but only as part of JNAND, which is simpler.
2002-09-05    gr     Added an is_block_erased function since this has been
                     removed from fs_nand_device.c. Added a test for ECC error
                     conditions.
2002-09-01   drh     Changed test to use nand_dev->is_erased instead of checking
                     here.
2002-08-15   drh     Changed nand_device to nand_dev to resolve multiple definition
2002-08-15   drh     Added spinners or block number printing as output
2002-08-08   drh     Created

===========================================================================*/

#include "jnand.h"
#include "jnand_msm.h"

/********************************************************************
 *    Main test task function
 *******************************************************************/

/* defines to control what code gets compiled in
 * so we do not have to edit the makefile all the time
 * to change the behavior of the test */

#define RUN_PATTERN
#define RUN_PATTERN_VERBOSE

/* These two are mutually exclusive */
#undef PRINT_SPINNERS
#define PRINT_BLOCKNOS

#if defined(PRINT_SPINNERS) && defined(PRINT_BLOCKNOS)
#error PRINT_SPINNERS and PRINT_BLOCKNOS are mutually exclusive
#endif

/* number of different characters to use to create spinners */
#define NUM_SPINNERS 6

/* Maximum size that sectors and pages can be.  Must use
 * this to define array sizes with
 */
#define MAX_SECTOR_SIZE 512
#define SPARE_SIZE      16
#define TOTAL_PAGE_SIZE (MAX_PAGE_SIZE+SPARE_SIZE)

/********************************************************************
 *    Global data
 *******************************************************************/

/* NAND device structure */
struct fs_device_data * nand_dev = 0;


char patterns[] =
{
#ifdef PATTERN_LARGE
#error code not present
#else
  0x50, 0xf0, 0x0f,
#endif
};


/* data to make spinning "alive" indicator */
/*                            {'|',  '/',  '-',  '|',  '\', '-'} */
char spinners[NUM_SPINNERS] = {0x7C, 0x2F, 0x2D, 0X7C, 0x5C, 0x2D};

/* Buffers to store page data in for reading and writing */
static unsigned char pbuf[TOTAL_PAGE_SIZE];
static unsigned char rbuf[TOTAL_PAGE_SIZE];


/***********************************************************************
FUNCTION      is_block_erased

DESCRIPTION   This function checks if every byte of every page in a given
              block is erased by repeatedly calling the is_page_erased
              function.

DEPENDENCIES  None

RETURN VALUE  TRUE if block is erased
              FALSE if block is not erased, or any error occurs during
                    checking
**********************************************************************/
static int
is_block_erased (fs_device_t self, block_id block)
{
  int i;
  int block_size = self->block_size (self);
  page_id start_page_no;

  start_page_no = (page_id) (block * block_size);

  for (i = 0; i < block_size; i++)
  {
    if (!self->is_erased (self, start_page_no+i))
      return FALSE;
  }

  return TRUE;
} /* END is_block_erased */



/********************************************************************
 *    Function to run patterns over the flash
 *******************************************************************/
fatal_code_type
do_pattern (int blockno, char patternval)
{
  int i, j;
  page_id current_page;
  int vfail = 0;

  KICK_WATCHDOG();

  if (nand_dev->bad_block_check(nand_dev, blockno) == 
      FS_DEVICE_BAD_BLOCK)
  {
    printf ("\n--- Skipping:  bad block %d\n", blockno);
    return ERR_BAD_BLOCK;
  }
  else
  {
    //printf ("\ngood block %d\n", blockno);
  }

  /* erase the block */
  if (nand_dev->erase_block(nand_dev, blockno) != FS_DEVICE_DONE)
  {
    printf ("--- Error: device failed during erase of block %d\n",
            blockno);
    return ERR_ERASE_FAIL;
  }

  /* Make sure the block was actually erased */
  if ((is_block_erased (nand_dev, blockno)) != TRUE)
  {
    return ERR_ERASE_FAIL;
  }


#ifdef RUN_PATTERN
  current_page = blockno * pages_in_block;
  KICK_WATCHDOG();

  /* run pattern over every page in the block we just erased */
  for (j=0; j<pages_in_block; j++)
  {
    KICK_WATCHDOG();
    if (nand_dev->write_page (nand_dev, current_page, pbuf)
        != FS_DEVICE_DONE )
    {
      printf ("--- Error: device failed during write of page 0x%x\n", 
              current_page);
      return ERR_WRITE_FAIL;
    }


    /* clear out readback buffer with pattern we do not use */
    for (i=0; i<page_size; i++)
    {
      rbuf[i] = 3;
    }

    /* read back data and verify it against source */
    if (nand_dev->read_page (nand_dev, current_page, rbuf)
        != FS_DEVICE_DONE )
    {
      printf ("Error: read fail of page 0x%x\n", current_page);
      return ERR_READ_FAIL;
    }

    for (i=0; i<page_size; i++)
    {
      if (pbuf[i] != rbuf[i])
      {
#ifdef RUN_PATTERN_VERBOSE
        printf ("     Verify fail at index %d in page %d, src 0x%x read 0x%x \n",
                i, current_page, pbuf[i], rbuf[i]);
#endif 
        vfail = 1;
       // return ERR_VERIFY_FAIL;
      }
    }
    current_page++;
  }
  if (vfail != 0)
  {
    return ERR_VERIFY_FAIL;
  }
  else
  {
    return ERR_OK;
  }
#endif /* RUN_PATTERN */

#if !defined(RUN_PATTERN)
  return ERR_OK;
#endif
}


/********************************************************************
 *    Main procedure of the NAND device driver layer test
 *******************************************************************/

void
nand_test (void)
{
  int i;
#ifndef RUN_BAD_FINDER
  int j, p;
  unsigned int pass = 0;
  int result;
  int numpats = sizeof(patterns);
#endif
#ifdef PRINT_SPINNERS
  int spinindex = 0;
#endif
  
  printf ("EFS2 NAND test started!\n");

  nand_dev=fs_nand_device_probe();

  if ( nand_dev == (struct fs_device_data *)FS_NO_DEVICE)
    {
    printf("Error: no nand_device found \n");
    return;
  }
  else
    {
    flash_name = nand_dev->device_name(nand_dev);
    printf("Found %s\n", flash_name);

    /* get some information about the device */
    block_count = nand_dev->block_count(nand_dev);
    pages_in_block = nand_dev->block_size(nand_dev);
    page_size = nand_dev->page_size(nand_dev);
    flash_name = nand_dev->device_name(nand_dev);

    /* calculate size of eraseable unit and max number of pages */
    eu_size = pages_in_block * page_size;
    max_pages = block_count * pages_in_block;

  }
  
#ifndef RUN_BAD_FINDER
  do
  {
    pass++;
    printf("\n++++  Pass 0x%x\n", pass);

    KICK_WATCHDOG();

    for (p=0; p<numpats ; p++)
    {
      /* init pattern buffer */
      for (j=0; j<MAX_PAGE_SIZE; j++)
      {
        pbuf[j] = patterns[p];
      }
      KICK_WATCHDOG();

#ifdef PRINT_BLOCKNOS
      printf("Pattern 0x%02x\n", patterns[p]);
      printf("  block    0x");
#else
      printf(" ");
#endif

      /* run pattern across every page in every block */
      for (i=0; i<block_count; i++)
      {
        KICK_WATCHDOG();
#ifdef PRINT_BLOCKNOS
        printf("\b\b\b%03X", i);
#else
#ifdef PRINT_SPINNERS
        printf ("\b%c", spinners[spinindex++]);
        if (spinindex == NUM_SPINNERS)
          spinindex = 0;
#endif
#endif
        result = do_pattern (i, patterns[p]);
        if (result != ERR_OK)
        {
          printf("\n--- Failed pattern 0x%x at block 0x%x pass 0x%x  ",
                 patterns[p], i, pass);
          switch (result)
          {
            case ERR_BAD_BLOCK:
              printf ("- Bad Block Detected\n");
              break;
            case ERR_ERASE_FAIL:
              printf ("- Not erased completely\n");
              break;
            case ERR_WRITE_FAIL:
              printf ("- Write Failed\n");
              break;
            case ERR_READ_FAIL:
              printf ("- Read Failed\n");
              break;
            case ERR_VERIFY_FAIL:
              printf ("- Verify failure\n");
              break;
            default:
              printf ("- Unknown error\n");
              break;
          }
#ifdef PRINT_BLOCKNOS
          printf("  block    0x");
#else
          printf(" ");
#endif
        } /* if */
      } /* for block count */
      printf("\n");
    } /* for patterns */

  } while (1);

#else /* RUN_BAD_FINDER */

  printf ("\n\n====== Running bad block finder ====== \n\n");
  for (i=0; i<block_count; i++)
  {
    KICK_WATCHDOG();
    if (nand_dev->bad_block_check(nand_dev, i) == 
        FS_DEVICE_BAD_BLOCK)
    {
      printf ("bad block %d\n", i);
    }
    else
    {
      // printf ("good block %d\n", i);
    }
  }
  printf ("\n\n====== Done ====== \n\n");
#endif /* !RUN_BAD_FINDER */
  return;
}



⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?