Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1495950
  • 博文数量: 267
  • 博客积分: 3010
  • 博客等级: 少校
  • 技术积分: 3089
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-05 17:09
个人简介

尊天命,尽人事

文章分类

全部博文(267)

文章存档

2017年(6)

2015年(4)

2014年(27)

2013年(52)

2012年(59)

2011年(120)

分类:

2011-09-02 19:11:02

上述的具体代码实现,可以去看

drivers\mtd\nand\nand_base.c中的nand_command_lp()函数中的代码:

 

/* Command latch cycle */

//对命令锁存,然后才能发送命令

         chip->cmd_ctrl(mtd, command & 0xff,

                          NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);

 

         if (column != -1 || page_addr != -1) {

                   int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE;

 

//先发送2col地址,构成整个列地址

                   /* 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;

                            chip->cmd_ctrl(mtd, column >> 8, ctrl);

                   }

//再发送3row地址,构成整个行地址

                   if (page_addr != -1) {

                            chip->cmd_ctrl(mtd, page_addr, ctrl);

                            chip->cmd_ctrl(mtd, page_addr >> 8,

                                            NAND_NCE | NAND_ALE);

                            /* One more address cycle for devices > 128MiB */

                            if (chip->chipsize > (128 << 20))

                                     chip->cmd_ctrl(mtd, page_addr >> 16,

                                                      NAND_NCE | NAND_ALE);

                   }

         }

这样就可以定位到我们要操作的位置,进行操作了。

 

2.软件方面:

Linux驱动原理

具体内部很多实现,已经包含在drivers\mtd\nand\nand_base.c中了

nand flash驱动加载识别nand类型过程】

在驱动加载的时候,会去调用:

nand_get_flash_type()

其中,就会对nand的类型和其他相关参数进行检查。

1  选中对应设备,如果此时只有一个nand 芯片,则此步可以省略

         /* Select the device */

         chip->select_chip(mtd, 0);

x

2  发读命令,去读取设备类型代码

         /* Send the command for reading device ID */

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

3  判断是哪个厂商的,哪个类型的flash

         /* Read manufacturer and device IDs */

         *maf_id = chip->read_byte(mtd);

         dev_id = chip->read_byte(mtd);

 

4  在事先已经定义好的nand flash类型中查找属于何种厂商和型号

         /* Lookup the flash id */

         for (i = 0; nand_flash_ids[i].name != NULL; i++) {

                   if (dev_id == nand_flash_ids[i].id) {

                            type =  &nand_flash_ids[i];

                            break;

                   }

         }

 

5  继续判断具体nand flash的各个参数,包括

芯片信息,Pagesize页大小,oobsizeoob的大小,blocksize块大小,buswidth总线宽度是8位还是16位。

 

如果页大小不是之前老的nand512B,而是新的nand2K或更大,则后面对应的发送给nand flash命令的的时候,调用的函数就由nand_command()变成nand_command_lp()了。

后者主要比前者多一发个命令:

chip->cmd_ctrl(mtd, column >> 8, ctrl);

即,多发一个列地址命令。

因为大页面(>2KB)的寻址需要2column,而小页面(512B)只需要1次的列地址。

具体可以参考nand flashdatasheet

 

6  接着会做一些其他初始化操作,包括最后调用nand_set_defaults()去实现的默认函数的挂载,如果你的nand flash驱动没有实现的话,就是挂载默认的了。

 

 

【模块加载原理】

这个内容太大,此处只是简单说说。

驱动加载的功能主要是probe函数实现的,主要去识别设备的类型和各个参数,并且为设备的使用进行正常的初始化。

对应卸载时候执行的remove函数,施放对应的,之前申请的一些资源。

 

MTD设备】

Linux下,将nand Flash等设备归属到MTD设备下进行统一管理。

Mtd,即memory technology deveice,即将nand看出是存储设备来管理。

之所以会这么说和这么做,是因为前面提高的nand flash和普通硬盘等设备的特殊性:

IO接口,最小单位是页,写前需擦除等,导致了,不能像平常对待硬盘等操作一样去操作nand flash,只能采取一些特殊方法,这就诞生了mtd设备的统一抽象层,将nand flashnor flash和其他类型的flash等设备,统一抽象成mtd设备来管理,根据这些设备的特点,上层实现了常见的操作函数封装,底层具体的内部实现,就需要驱动设计者自己来实现了。

 

MTD设备和硬盘设备之前的区别

HARD drives

MTD device

连续的扇区

连续的可擦除块

扇区都很小(512B,1024B)

可擦除块比较大 (32KB,128KB)

主要通过两个操作对其维护操作:读扇区,写扇区

主要通过三个操作对其维护操作:从擦除块中读,写入擦除块,擦写可擦除块

坏快被重新映射,并且被硬件隐藏起来了(至少是在如今常见的LBA硬盘设备中是如此)

坏的可擦除块没有被隐藏,软件中要处理对应的坏块问题。

HDD扇区没有擦写寿命超出的问题。

可擦除块是有擦除次数限制的,大概是104-105.

 

Linuxnand flash驱动编写步骤简介】

1.       了解硬件的nand flash的各个参数和工作原理

具体参考nand flashdatasheet,主要包括,自己nand flash的厂商,型号等。

Nand flash的页大小,oob大小,块大小,位宽8bit还是16bit

工作原理,上面已经做了一定描述,不清楚的,可以参考datasheet,多看看,就会明白很多。

 

2.       按照linux下驱动编写规范编写nand flash驱动,

可以参考其他已经有的驱动,比如内核源码中已经有的

drivers\mtd\nand\s3c2410.c

就是个很好的例子。

自己以其为模板,实现自己板子的nand flash驱动。

其实主要工作就是,实现

static struct platform_driver s3c2410_nand_driver = {

         .probe                 = s3c2410_nand_probe,

         .remove              = s3c2410_nand_remove,

         .suspend  = s3c24xx_nand_suspend,

         .resume              = s3c24xx_nand_resume,

         .driver                 = {

                   .name        = "s3c2410-nand",

                   .owner       = THIS_MODULE,

         },

};

中的

XXX_nand_probe函数

XXX_nand_remove函数

XXX_nand_enable_hwecc,如果支持硬件ecc的话。

nand flash的读写,这两个函数,实现了对nand的具体操作。

 

LinuxNand Flash驱动编写简单步骤】

软件和硬件知识,都已经了解的话,由于上层的linux mtd框架中,已经完全封装好了,对nand flashwrite pagewrite oob等相关函数的实现,那么剩下的只是相对来说已经是很少量的,关于nand 驱动具体内部操作方面的工作:

1.初始化

先是在nand 芯片初始化的时候,对其

XXX_nand_init_chip()

给对应的芯片chip赋给对应的

XXX_nand_read_bufXXX_nand_write_buf等函数:

                   chip->cmd_ctrl  = XXX_nand_hwcontrol;

                   chip->dev_ready = XXX_nand_devready;

                   chip->read_buf  = XXX_nand_read_buf;

                   chip->write_buf  = XXX_nand_write_buf;

以实现后续的对nand芯片的操作。

 

然后根据ecc类型,赋给对应的ecc的校验与纠错函数:

                          chip->ecc.hwctl     = XXX_nand_enable_hwecc;

                          chip->ecc.calculate = XXX _nand_calculate_ecc;

 

3.       实现上面提到的对应的各个函数,关于如何实现,参考一下其他nand驱动,就会理解很多了。

4.       驱动测试,参考具体的 ldd3Linux Device Driver version 3)的测试相关部分内容。

 

说得很乱,希望对大家有些帮助。

 

MTD设备驱动推荐文章】

关于mtd设备驱动,感兴趣的可以去参考

MTD原始设备与FLASH硬件驱动的对话

MTD原始设备与FLASH硬件驱动的对话-

那里,算是比较详细地介绍了整个流程,方便大家理解整个mtd框架和nand flash驱动。

 

【引用文章】

Brief Intro of Nand Flash

Samsung K9F4G08U0M.pdf Samsung Nand Flash Datasheet nand型号是K9F4G08U0M

nand falsh read operation

 

阅读(625) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~