uboot-nand

   226  void nand_init(void)
   227  {
   228          /*
   229           * Init board specific nand support
   230           */
   231          puts("nand_init \n");
   232          nand_info[0].priv = &nand_chip;
   233          nand_chip.IO_ADDR_R = nand_chip.IO_ADDR_W =
   234                  (void  __iomem *)CONFIG_SYS_NAND_BASE;
   235          board_nand_init(&nand_chip);
   236
   237          if (nand_chip.select_chip)
   238                  nand_chip.select_chip(&nand_info[0], 0);
   239
   240          /* NAND chip may require reset after power-on */
   241          nand_command(0, 0, 0, NAND_CMD_RESET);
   242          puts("nand_init end \n");
   243  }
   244

233行:给IO赋值CONFIG_SYS_NAND_BASE

235行:board_nand_init

  972  /*
   973   * Board-specific NAND initialization. The following members of the
   974   * argument are board-specific:
   975   * - IO_ADDR_R: address to read the 8 I/O lines of the flash device
   976   * - IO_ADDR_W: address to write the 8 I/O lines of the flash device
   977   * - cmd_ctrl: hardwarespecific function for accesing control-lines
   978   * - waitfunc: hardwarespecific function for accesing device ready/busy line
   979   * - ecc.hwctl: function to enable (reset) hardware ecc generator
   980   * - ecc.mode: mode of ecc, see defines
   981   * - chip_delay: chip dependent delay for transfering data from array to
   982   *   read regs (tR)
   983   * - options: various chip options. They can partly be set to inform
   984   *   nand_scan about special functionality. See the defines for further
   985   *   explanation
   986   */
   987  int board_nand_init(struct nand_chip *nand)
   988  {
   989          int32_t gpmc_config = 0;
   990          int cs = cs_next++;
   991          int err = 0;
   992          /*
   993           * xloader/Uboot's gpmc configuration would have configured GPMC for
   994           * nand type of memory. The following logic scans and latches on to the
   995           * first CS with NAND type memory.
   996           * TBD: need to make this logic generic to handle multiple CS NAND
   997           * devices.
   998           */
   999          puts("board_nand_init start\n");
  1000          while (cs < GPMC_MAX_CS) {
  1001                  /* Check if NAND type is set */
  1002                  if ((readl(&gpmc_cfg->cs[cs].config1) & 0xC00) == 0x800) {
  1003                          /* Found it!! */
  1004                          break;
  1005                  }
  1006                  cs++;
  1007          }
  1008          if (cs >= GPMC_MAX_CS) {
  1009                  printf("nand: error: Unable to find NAND settings in "
  1010                          "GPMC Configuration - quitting\n");
  1011                  return -ENODEV;
  1012          }
  1013          printf("board_nand_init mid %x \n", &gpmc_cfg->cs[cs].config1);
  1014          gpmc_config = readl(&gpmc_cfg->config);
  1015          /* Disable Write protect */
  1016          gpmc_config |= 0x10;
  1017          writel(gpmc_config, &gpmc_cfg->config);
  1018
  1019          nand->IO_ADDR_R = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
  1020          nand->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
  1021          omap_nand_info[cs].control = NULL;
  1022          omap_nand_info[cs].cs = cs;
  1023          omap_nand_info[cs].ws = wscfg[cs];
  1024          nand->priv      = &omap_nand_info[cs];
  1025          nand->cmd_ctrl  = omap_nand_hwcontrol;
  1026          nand->options   |= NAND_NO_PADDING | NAND_CACHEPRG;
  1027          nand->chip_delay = 100;
  1028          nand->ecc.layout = &omap_ecclayout;
  1029
  1030          /* configure driver and controller based on NAND device bus-width */
  1031          gpmc_config = readl(&gpmc_cfg->cs[cs].config1);
  1032  #if defined(CONFIG_SYS_NAND_BUSWIDTH_16BIT)
  1033          nand->options |= NAND_BUSWIDTH_16;
  1034          writel(gpmc_config | (0x1 << 12), &gpmc_cfg->cs[cs].config1);
  1035  #else
  1036          nand->options &= ~NAND_BUSWIDTH_16;
  1037          writel(gpmc_config & ~(0x1 << 12), &gpmc_cfg->cs[cs].config1);
  1038  #endif
  1039                  int maf_id,dev_id;
  1040          read_nand_id(&maf_id, &dev_id);
  1041          printf("+++++++++++++++++++maf_id=0x%x,dev_id=0x%x\n",maf_id,dev_id);
  1042          /* select ECC scheme */
  1043  #if defined(CONFIG_NAND_OMAP_ECCSCHEME)
  1044          // err = omap_select_ecc_scheme(nand, CONFIG_NAND_OMAP_ECCSCHEME,
  1045          //              CONFIG_SYS_NAND_PAGE_SIZE, CONFIG_SYS_NAND_OOBSIZE);
  1046  #ifdef CONFIG_SPL_BUILD
  1047                  err = omap_select_ecc_scheme(nand, OMAP_ECC_BCH16_CODE_HW,
  1048                          CONFIG_SYS_NAND_PAGE_SIZE, CONFIG_SYS_NAND_OOBSIZE);
  1049  #else
  1050                  err = omap_select_ecc_scheme(nand, OMAP_ECC_BCH8_CODE_HW,
  1051                          CONFIG_SYS_NAND_PAGE_SIZE, CONFIG_SYS_NAND_OOBSIZE);
  1052  #endif
  1053  #else
  1054          /* pagesize and oobsize are not required to configure sw ecc-scheme */
  1055          err = omap_select_ecc_scheme(nand, OMAP_ECC_HAM1_CODE_SW,
  1056                          0, 0);
  1057  #endif
  1058          if (err)
  1059                  return err;
  1060
  1061  #ifdef CONFIG_NAND_OMAP_GPMC_PREFETCH
  1062          nand->read_buf = omap_nand_read_prefetch;
  1063  #else
  1064          if (nand->options & NAND_BUSWIDTH_16)
  1065                  nand->read_buf = nand_read_buf16;
  1066          else
  1067                  nand->read_buf = nand_read_buf;
  1068  #endif
  1069
  1070          nand->dev_ready = omap_dev_ready;
  1071          printf("+++++++++++++++++++maf_id=0x%x,dev_id=0x%x\n",maf_id,dev_id);
  1072          return 0;
  1073  }
  1074

990行:这个是赋值。

  38  static uint8_t cs_next;

看到cs_next =0;

1000~1007行:选取cs

读取config1值:读取nand flash

 1014~1017行:Disable Write protect

接下来就是一些配置

nand->IO_ADDR_R = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;

    nand->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;

    omap_nand_info[cs].control = NULL;

    omap_nand_info[cs].cs = cs;

    omap_nand_info[cs].ws = wscfg[cs];

    nand->priv  = &omap_nand_info[cs];

    nand->cmd_ctrl  = omap_nand_hwcontrol;

    nand->options   |= NAND_NO_PADDING | NAND_CACHEPRG;

    nand->chip_delay = 100;

    nand->ecc.layout = &omap_ecclayout;

1030~1038行:配置bus宽度

1040读取ID :read_nand_id

  55  int read_nand_id(int* maf_id, int* dev_id)
    56  {
    57          struct nand_chip this;
    58          init_nand_chip(&this);
    59
    60          while (!this.dev_ready(&this))
    61                          ;
    62
    63          void (*hwctrl)(struct nand_chip *nand, int cmd,
    64                          unsigned int ctrl) = this.cmd_ctrl;
    65
    66          /* Begin command latch cycle */
    67          hwctrl(&this, NAND_CMD_RESET, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
    68
    69          hwctrl(&this, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
    70          while (!this.dev_ready(&this))
    71                  ;
    72
    73          hwctrl(&this, NAND_CMD_READID, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
    74
    75          /* Set ALE and clear CLE to start address cycle */
    76          /* Column address */
    77          hwctrl(&this, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE); /* A[7:0] */
    78          hwctrl(&this, 0, NAND_CTRL_ALE); /* A[11:9] */
    79          /* Row address */
    80          hwctrl(&this, 0, NAND_CTRL_ALE); /* A[19:12] */
    81          hwctrl(&this, 0, NAND_CTRL_ALE); /* A[27:20] */
    82  #ifdef CONFIG_SYS_NAND_5_ADDR_CYCLE
    83          /* One more address cycle for devices > 128MiB */
    84          hwctrl(&this, 0, NAND_CTRL_ALE); /* A[31:28] */
    85  #endif
    86          hwctrl(&this, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
    87
    88          *maf_id = readb(this.IO_ADDR_R);
    89          *dev_id = readb(this.IO_ADDR_R);
    90
    91          return 0;
    92  }

58行:58          init_nand_chip(&this);

  43  static int init_nand_chip(struct nand_chip* nand)
    44  {
    45          int cs = 0;
    46          nand->IO_ADDR_R = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
    47          nand->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
    48          nand->cmd_ctrl  = omap_nand_hwcontrol;
    49          nand->options   |= NAND_NO_PADDING | NAND_CACHEPRG;
    50          nand->chip_delay = 100;
    51          nand->ecc.layout = &omap_ecclayout;
    52          nand->dev_ready = omap_spl_dev_ready;
    53  }

60行:首先判断dev_ready 

  9  /*#ifdef CONFIG_SPL_BUILD*/
    10  /* Check wait pin as dev ready indicator */
    11  static int omap_spl_dev_ready(struct nand_chip *mtd)
    12  {
    13          return gpmc_cfg->status & (1 << 8);
    14  }
    15  /*#endif*/ /* 

判断读取状态

看是否准备好。

 63行:这个ctrl

static void omap_nand_hwcontrol(struct nand_chip* nand, int32_t cmd,
				uint32_t ctrl)
{
	int cs = 0;
	register struct nand_chip *this = nand;

	/*
	 * Point the IO_ADDR to DATA and ADDRESS registers instead
	 * of chip address
	 */
	switch (ctrl) {
	case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
		this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
		break;
	case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
		this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_adr;
		break;
	case NAND_CTRL_CHANGE | NAND_NCE:
		this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
		break;
	}

	if (cmd != NAND_CMD_NONE)
		writeb(cmd, this->IO_ADDR_W);
}

看下面地址。

总的过程:

第1步:写入reset命令。

等待reset完毕。

第2步:写入READID命令。

写入0列0行地址。

读取id,退出这个函数

接下来

 1050 行                 err = omap_select_ecc_scheme(nand, OMAP_ECC_BCH8_CODE_HW,
                   CONFIG_SYS_NAND_PAGE_SIZE, CONFIG_SYS_NAND_OOBSIZE);

  724  /**
   725   * omap_select_ecc_scheme - configures driver for particular ecc-scheme
   726   * @nand: NAND chip device structure
   727   * @ecc_scheme: ecc scheme to configure
   728   * @pagesize: number of main-area bytes per page of NAND device
   729   * @oobsize: number of OOB/spare bytes per page of NAND device
   730   */
   731  static int omap_select_ecc_scheme(struct nand_chip *nand,
   732          enum omap_ecc ecc_scheme, unsigned int pagesize, unsigned int oobsize) {
   733          struct omap_nand_info   *info           = nand->priv;
   734          struct nand_ecclayout   *ecclayout      = &omap_ecclayout;
   735          int eccsteps = pagesize / SECTOR_BYTES;
   736          int i;
   737          printf("ecc_scheme %d pagesize = %x  oobsize %x ", ecc_scheme, pagesize,oobsize);
   738          switch (ecc_scheme) {
   739          case OMAP_ECC_HAM1_CODE_SW:
   740                  debug("nand: selected OMAP_ECC_HAM1_CODE_SW\n");
   741                  /* For this ecc-scheme, ecc.bytes, ecc.layout, ... are
   742                   * initialized in nand_scan_tail(), so just set ecc.mode */
   743                  info->control           = NULL;
   744                  nand->ecc.mode          = NAND_ECC_SOFT;
   745                  nand->ecc.layout        = NULL;
   746                  nand->ecc.size          = 0;
   747                  break;
   748
   749          case OMAP_ECC_HAM1_CODE_HW:
   750                  debug("nand: selected OMAP_ECC_HAM1_CODE_HW\n");
   751                  /* check ecc-scheme requirements before updating ecc info */
   752                  if ((3 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
   753                          printf("nand: error: insufficient OOB: require=%d\n", (
   754                                  (3 * eccsteps) + BADBLOCK_MARKER_LENGTH));
   755                          return -EINVAL;
   756                  }
   757                  info->control           = NULL;
   758                  /* populate ecc specific fields */
   759                  memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
   760                  nand->ecc.mode          = NAND_ECC_HW;
   761                  nand->ecc.strength      = 1;
   762                  nand->ecc.size          = SECTOR_BYTES;
   763                  nand->ecc.bytes         = 3;
   764                  nand->ecc.hwctl         = omap_enable_hwecc;
   765                  nand->ecc.correct       = omap_correct_data;
   766                  nand->ecc.calculate     = omap_calculate_ecc;
   767                  /* define ecc-layout */
   768                  ecclayout->eccbytes     = nand->ecc.bytes * eccsteps;
   769                  for (i = 0; i < ecclayout->eccbytes; i++) {
   770                          if (nand->options & NAND_BUSWIDTH_16)
   771                                  ecclayout->eccpos[i] = i + 2;
   772                          else
   773                                  ecclayout->eccpos[i] = i + 1;
   774                  }
   775                  ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
   776                  ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
   777                                                  BADBLOCK_MARKER_LENGTH;
   778                  break;
   779
   780          case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
   781  #ifdef CONFIG_BCH
   782                  debug("nand: selected OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n");
   783                  /* check ecc-scheme requirements before updating ecc info */
   784                  if ((13 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
   785                          printf("nand: error: insufficient OOB: require=%d\n", (
   786                                  (13 * eccsteps) + BADBLOCK_MARKER_LENGTH));
   787                          return -EINVAL;
   788                  }
   789                  /* check if BCH S/W library can be used for error detection */
   790                  info->control = init_bch(13, 8, 0x201b);
   791                  if (!info->control) {
   792                          printf("nand: error: could not init_bch()\n");
   793                          return -ENODEV;
   794                  }
   795                  /* populate ecc specific fields */
   796                  memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
   797                  nand->ecc.mode          = NAND_ECC_HW;
   798                  nand->ecc.strength      = 8;
   799                  nand->ecc.size          = SECTOR_BYTES;
   800                  nand->ecc.bytes         = 13;
   801                  nand->ecc.hwctl         = omap_enable_hwecc;
   802                  nand->ecc.correct       = omap_correct_data_bch_sw;
   803                  nand->ecc.calculate     = omap_calculate_ecc;
   804                  /* define ecc-layout */
   805                  ecclayout->eccbytes     = nand->ecc.bytes * eccsteps;
   806                  ecclayout->eccpos[0]    = BADBLOCK_MARKER_LENGTH;
   807                  for (i = 1; i < ecclayout->eccbytes; i++) {
   808                          if (i % nand->ecc.bytes)
   809                                  ecclayout->eccpos[i] =
   810                                                  ecclayout->eccpos[i - 1] + 1;
   811                          else
   812                                  ecclayout->eccpos[i] =
   813                                                  ecclayout->eccpos[i - 1] + 2;
   814                  }
   815                  ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
   816                  ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
   817                                                  BADBLOCK_MARKER_LENGTH;
   818                  break;
   819  #else
   820                  printf("nand: error: CONFIG_BCH required for ECC\n");
   821                  return -EINVAL;
   822  #endif
   823
   824          case OMAP_ECC_BCH8_CODE_HW:
   825  #ifdef CONFIG_NAND_OMAP_ELM
   826                  debug("nand: selected OMAP_ECC_BCH8_CODE_HW\n");
   827                  /* check ecc-scheme requirements before updating ecc info */
   828                  if ((14 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
   829                          printf("nand: error: insufficient OOB: require=%d\n", (
   830                                  (14 * eccsteps) + BADBLOCK_MARKER_LENGTH));
   831                          return -EINVAL;
   832                  }
   833                  /* intialize ELM for ECC error detection */
   834                  elm_init();
   835                  info->control           = NULL;
   836                  /* populate ecc specific fields */
   837                  memset(&nand->ecc, 0, sizeof(struct nand_ecc_ctrl));
   838                  nand->ecc.mode          = NAND_ECC_HW;
   839                  nand->ecc.strength      = 8;
   840                  nand->ecc.size          = SECTOR_BYTES;
   841                  nand->ecc.bytes         = 14;
   842                  nand->ecc.hwctl         = omap_enable_hwecc;
   843                  nand->ecc.correct       = omap_correct_data_bch;
   844                  nand->ecc.calculate     = omap_calculate_ecc;
   845                  nand->ecc.read_page     = omap_read_page_bch;
   846                  /* define ecc-layout */
   847                  ecclayout->eccbytes     = nand->ecc.bytes * eccsteps;
   848                  for (i = 0; i < ecclayout->eccbytes; i++)
   849                          ecclayout->eccpos[i] = i + BADBLOCK_MARKER_LENGTH;
   850                  ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
   851                  ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
   852                                                  BADBLOCK_MARKER_LENGTH;
   853                  printf("-------------------------------------\n");
   854                  printf("ecclayout->eccbytes %d  off %d  len %d\n",ecclayout->eccbytes,\
   855                  ecclayout->oobfree[0].offset,ecclayout->oobfree[0].length);
   856                  printf("ooblen %d \n", oobsize);
   857                  break;
   858  #else
   859                  printf("nand: error: CONFIG_NAND_OMAP_ELM required for ECC\n");
   860                  return -EINVAL;
   861  #endif
   862
   863          case OMAP_ECC_BCH16_CODE_HW:
   864  #ifdef CONFIG_NAND_OMAP_ELM
   865                  debug("nand: using OMAP_ECC_BCH16_CODE_HW\n");
   866                  /* check ecc-scheme requirements before updating ecc info */
   867                  if ((26 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
   868                          printf("nand: error: insufficient OOB: require=%d\n", (
   869                                  (26 * eccsteps) + BADBLOCK_MARKER_LENGTH));
   870                          return -EINVAL;
   871                  }
   872                  /* intialize ELM for ECC error detection */
   873                  elm_init();
   874                  /* populate ecc specific fields */
   875                  nand->ecc.mode          = NAND_ECC_HW;
   876                  nand->ecc.size          = SECTOR_BYTES;
   877                  nand->ecc.bytes         = 26;
   878                  nand->ecc.strength      = 16;
   879                  nand->ecc.hwctl         = omap_enable_hwecc;
   880                  nand->ecc.correct       = omap_correct_data_bch;
   881                  nand->ecc.calculate     = omap_calculate_ecc;
   882                  nand->ecc.read_page     = omap_read_page_bch;
   883                  /* define ecc-layout */
   884                  ecclayout->eccbytes     = nand->ecc.bytes * eccsteps;
   885                  for (i = 0; i < ecclayout->eccbytes; i++)
   886                          ecclayout->eccpos[i] = i + BADBLOCK_MARKER_LENGTH;
   887                  ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
   888                  ecclayout->oobfree[0].length = oobsize - nand->ecc.bytes -
   889                                                  BADBLOCK_MARKER_LENGTH;
   890                  break;
   891  #else
   892                  printf("nand: error: CONFIG_NAND_OMAP_ELM required for ECC\n");
   893                  return -EINVAL;
   894  #endif
   895          default:
   896                  debug("nand: error: ecc scheme not enabled or supported\n");
   897                  return -EINVAL;
   898          }
   899
   900          /* nand_scan_tail() sets ham1 sw ecc; hw ecc layout is set by driver */
   901          if (ecc_scheme != OMAP_ECC_HAM1_CODE_SW)
   902                  nand->ecc.layout = ecclayout;
   903
   904          info->ecc_scheme = ecc_scheme;
   905          return 0;
   906  }
   907

根据传:入参数OMAP_ECC_BCH8_CODE_HW运行

834行:初始化elm

/**
 * elm_reset - Do a soft reset of ELM
 *
 * Perform a soft reset of ELM and return after reset is done.
 */
void elm_reset(void)
{
	/* initiate reset */
	writel((readl(&elm_cfg->sysconfig) | ELM_SYSCONFIG_SOFTRESET),
			&elm_cfg->sysconfig);

	/* wait for reset complete and normal operation */
	while ((readl(&elm_cfg->sysstatus) & ELM_SYSSTATUS_RESETDONE) !=
		ELM_SYSSTATUS_RESETDONE)
		;
}

/**
 * elm_init - Initialize ELM module
 *
 * Initialize ELM support. Currently it does only base address init
 * and ELM reset.
 */
void elm_init(void)
{
	elm_cfg = (struct elm *)ELM_BASE;
	elm_reset();
}

        接下来:

        nand->ecc.strength    = 8;

        nand->ecc.size      = SECTOR_BYTES;//每个扇区512字节

        nand->ecc.bytes     = 14;//每个扇区的oob占用字节

接下来对读取一页的数据分析:

nand_read_page

  122  static int nand_read_page(int block, int page, void *dst)
   123  {
   124          struct nand_chip *this = nand_info[0].priv;
   125          u_char ecc_calc[ECCTOTAL];
   126          u_char ecc_code[ECCTOTAL];
   127          u_char oob_data[CONFIG_SYS_NAND_OOBSIZE];
   128          int i, j;
   129          int eccsize = CONFIG_SYS_NAND_ECCSIZE;      //512
   130          int eccbytes = CONFIG_SYS_NAND_ECCBYTES;
   131          int eccsteps = ECCSTEPS;//8
   132          uint8_t *p = dst;
   133          uint32_t data_pos = 0;
   134          uint8_t *oob = &oob_data[0] + nand_ecc_pos[0];
   135          uint32_t oob_pos = eccsize * eccsteps + nand_ecc_pos[0];
   136
   137          nand_command(block, page, 0, NAND_CMD_READ0);
   138          // printf("nand_read_page =================\n");
   139          for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
   140                  this->ecc.hwctl(&nand_info[0], NAND_ECC_READ);
   141                  nand_command(block, page, data_pos, NAND_CMD_RNDOUT);
   142
   143
   144                  this->read_buf(&nand_info[0], p, eccsize);
   145
   146
   147
   148                  nand_command(block, page, oob_pos, NAND_CMD_RNDOUT);
   149
   150                  this->read_buf(&nand_info[0], oob, eccbytes);
   151                  this->ecc.calculate(&nand_info[0], p, &ecc_calc[i]);
   152
   153                  data_pos += eccsize;
   154                  oob_pos += eccbytes;
   155                  oob += eccbytes;
   156          }
   157          // printf("nand_read_page end=================\n");
   158          /* Pick the ECC bytes out of the oob data */
   159          for (i = 0; i < ECCTOTAL; i++)
   160                  ecc_code[i] = oob_data[nand_ecc_pos[i]];
   161
   162          eccsteps = ECCSTEPS;
   163          p = dst;
   164
   165          for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
   166                  /* No chance to do something with the possible error message
   167                   * from correct_data(). We just hope that all possible errors
   168                   * are corrected by this routine.
   169                   */
   170                  this->ecc.correct(&nand_info[0], p, &ecc_code[i], &ecc_calc[i]);
   171          }
   172
   173          return 0;
   174  }
   175

139~156行:循环8次使用随机读取命令读取数据。

对于每个扇区:首先使用随机读取命令读取512个字节,然后位置增加512,然后使用随机读取命令读取oob,oob第一次在页尾,读取26个字节,然后位置增加26,就这样读取数据。

还有计算oob就是读取elm计算后的16字节赋给计算的值。

165行循环:接下来就是计算nand是否读取正确。配置lem的type 为BCH8,计算和比较

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值