文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>arm-linux东东之nand之3: nand_scan_ident出生

arm-linux东东之nand之3: nand_scan_ident出生

时间:2009-03-23  来源:qiuhuafeng

 

三 nand_scan_ident出生

读这样的代码.会不会觉得我很无聊.不过还得继续nand_scan_ident.500)this.width=500;" border=0>

2403行如果你的NAND是16的,就必须在进入nand_scan_ident之前做这样的一个语句:

Chip->options | =NAND_BUSWIDTH_16,表示我的NAND是16数据宽的.

2405行调用nand_set_defaults

 

 

500)this.width=500;" border=0>    

给chip 值.没有给的.这里给defaults.

对照一下s3c2410_nand_init_chip

 

500)this.width=500;" border=0>          

好回到nand_scan_ident中:

500)this.width=500;" border=0>    

2404行调用nand_get_flash_type

500)this.width=500;" border=0>

   

2243行调用select_chip.不知道你记不记得以前我们说过的

       chip->select_chip  = s3c2410_nand_select_chip;

于是进入s3c2410_nand_select_chip

  static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
{
 struct s3c2410_nand_info *info;
 struct s3c2410_nand_mtd *nmtd;
 struct nand_chip *this = mtd->priv;
 unsigned long cur;
         nmtd = this->priv;
 info = nmtd->info;
       if (chip != -1 && allow_clk_stop(info))
  clk_enable(info->clk);
 cur = readl(info->sel_reg);
        if (chip == -1) {
  cur |= info->sel_bit;
 } else {
  if (nmtd->set != NULL && chip > nmtd->set->nr_chips) {
   dev_err(info->device, "invalid chip %d\n", chip);
   return;
  }
  if (info->platform != NULL) {
   if (info->platform->select_chip != NULL)
    (info->platform->select_chip) (nmtd->set, chip);
  }
  cur &= ~info->sel_bit;
 }
       writel(cur, info->sel_reg);
       if (chip == -1 && allow_clk_stop(info))
  clk_disable(info->clk);
}
 

这里chip 就是0

250行就会被调用

251行读寄存器NFCONF.还记得不:

       info->sel_reg   = regs + S3C2440_NFCONT;

       info->sel_bit   = S3C2440_NFCONT_nFCE;

265行取反.也就是以前我们说的. Enable chip select

经过这么一调用NAND控制器就跑起来了.

回到nand_get_flash_type中来.

2246行chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);

接下来要说NAND协议了.请注意.

于是调用

static void nand_command(struct mtd_info *mtd, unsigned int command,
    int column, int page_addr)
{
 register struct nand_chip *chip = mtd->priv;
 int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;

 /*
  * Write out the command to the device.
  */
 if (command == NAND_CMD_SEQIN) {
  int readcmd;

  if (column >= mtd->writesize) {
   /* OOB area */
   column -= mtd->writesize;
   readcmd = NAND_CMD_READOOB;
  } else if (column < 256) {
   /* First 256 bytes --> READ0 */
   readcmd = NAND_CMD_READ0;
  } else {
   column -= 256;
   readcmd = NAND_CMD_READ1;
  }
  chip->cmd_ctrl(mtd, readcmd, ctrl);
  ctrl &= ~NAND_CTRL_CHANGE;
 }
 chip->cmd_ctrl(mtd, command, ctrl);

 /*
  * Address cycle, when necessary
  */
 ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;
 /* Serially input address */
 if (column != -1) {
  /* Adjust columns for 16 bit buswidth */
  if (chip->options & NAND_BUSWIDTH_16)
   column >>= 1;
  chip->cmd_ctrl(mtd, column, ctrl);
  ctrl &= ~NAND_CTRL_CHANGE;
 }
 if (page_addr != -1) {
  chip->cmd_ctrl(mtd, page_addr, ctrl);
  ctrl &= ~NAND_CTRL_CHANGE;
  chip->cmd_ctrl(mtd, page_addr >> 8, ctrl);
  /* One more address cycle for devices > 32MiB */
  if (chip->chipsize > (32 << 20))
   chip->cmd_ctrl(mtd, page_addr >> 16, ctrl);
 }
 chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);

 /*
  * program and erase have their own busy handlers
  * status and sequential in needs no delay
  */
 switch (command) {

 case NAND_CMD_PAGEPROG:
 case NAND_CMD_ERASE1:
 case NAND_CMD_ERASE2:
 case NAND_CMD_SEQIN:
 case NAND_CMD_STATUS:
  return;

 case NAND_CMD_RESET:
  if (chip->dev_ready)
   break;
  udelay(chip->chip_delay);
  chip->cmd_ctrl(mtd, NAND_CMD_STATUS,
          NAND_CTRL_CLE | NAND_CTRL_CHANGE);
  chip->cmd_ctrl(mtd,
          NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
  while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ;
  return;

  /* This applies to read commands */
 default:
  /*
   * If we don't have access to the busy pin, we apply the given
   * command delay
   */
  if (!chip->dev_ready) {
   udelay(chip->chip_delay);
   return;
  }
 }
 /* Apply this short delay always to ensure that we do wait tWB in
  * any case on any machine. */
 ndelay(100);

 nand_wait_ready(mtd);
}

 

我们来看下参数.mtd没有问题吧.command是命令.大概就有这么些命令:

#define NAND_CMD_READ0             0

#define NAND_CMD_READ1             1

#define NAND_CMD_RNDOUT          5

#define NAND_CMD_PAGEPROG      0x10

#define NAND_CMD_READOOB 0x50

#define NAND_CMD_ERASE1            0x60

#define NAND_CMD_STATUS            0x70

#define NAND_CMD_STATUS_MULTI      0x71

#define NAND_CMD_SEQIN              0x80

#define NAND_CMD_RNDIN             0x85

#define NAND_CMD_READID           0x90

#define NAND_CMD_ERASE2            0xd0

#define NAND_CMD_RESET             0xff

而这里的命令就是: NAND_CMD_READID

Column是列地址. page_addr是页地址.很多NAND一页就是512+16.

写一页数据怎么写呢?

一页分A区/B区/C区

A区就是512的上半部就是前一个256

B区就是512的下半部就是后一个256

C区就是那16个

通过命令选中区以后就可以通过Column来选择那个字

OK.很多NAND又分块.一块有几个页

 

500)this.width=500;" border=0>    

这个图说明:一个块有32个页也就是说在page_addr分出5位来对页寻址.其他的就对块寻址.于是就这样发地址:

 

500)this.width=500;" border=0>  

A0-A7就是Column地址 A9-A13就是页地址A14-A25就块地址.当然你的NAND可能与我的不同.我的是64M的.*L表示为0.

   
相关阅读 更多 +
排行榜 更多 +
奇境小镇MOD作弊菜单

奇境小镇MOD作弊菜单

角色扮演 下载
黑暗荒野2无限金币版

黑暗荒野2无限金币版

角色扮演 下载
骑战烈火之剑作弊菜单版

骑战烈火之剑作弊菜单版

角色扮演 下载