nand flash基础知识

nand flash上为什么只有地址线。如何传输数据和命令:
地址,数据,命令是复用的。使用ALE,CLE来进行区分的
通过RnB引脚来区分数据操作是否完成

nand flash驱动分析

从入口函数开始看:

865 static struct platform_driver s3c2412_nand_driver = {
866     .probe      = s3c2412_nand_probe,
867     .remove     = s3c2410_nand_remove,
868     .suspend    = s3c24xx_nand_suspend,
869     .resume     = s3c24xx_nand_resume,
870     .driver     = {
871         .name   = "s3c2412-nand",
872         .owner  = THIS_MODULE,
873     },
874 };
struct mtd_info *s3c_mtd;

设备和驱动匹配上之后,会调用 s3c2412_nand_probe

s3c2412_nand_probe

1.分配
struct mtd_info mtd;
struct nand_chip chip;
这个两个关键的结构体:
代码:

struct s3c2410_nand_info *info;
info = kmalloc(sizeof(*info), GFP_KERNEL);

其中的数据结构定义为:

 92 struct s3c2410_nand_mtd {93     struct mtd_info         mtd;94     struct nand_chip        chip;95     struct s3c2410_nand_set     *set;96     struct s3c2410_nand_info    *info;97     int             scan_res;98 };108 struct s3c2410_nand_info {
109     /* mtd info */
110     struct nand_hw_control      controller;
111     struct s3c2410_nand_mtd     *mtds;
112     struct s3c2410_platform_nand    *platform;
113
114     /* device info */
115     struct device           *device;
116     struct resource         *area;
117     struct clk          *clk;
118     void __iomem            *regs;
119     void __iomem            *sel_reg;
120     int             sel_bit;
121     int             mtd_count;
122
123     enum s3c_cpu_type       cpu_type;
124 };

可见非配的内存,包含了两个重要的结构体。
其中struct s3c2410_nand_set *set;为设备信息

 [0] = {.name       = "NAND",.nr_chips   = 1,.nr_partitions = ARRAY_SIZE(smdk_default_nand_part),.partitions   = smdk_default_nand_part,},
};/* choose a set of timings which should suit most 512Mbit* chips and beyond.
*/static struct s3c2410_platform_nand smdk_nand_info = {.tacls     = 20,.twrph0       = 60,.twrph1       = 20,.nr_sets  = ARRAY_SIZE(smdk_nand_sets),.sets     = smdk_nand_sets,
};
  1. 设置nand chip结构体,根据设备信息,映射寄存器地址
667 static int s3c24xx_nand_probe(struct platform_device *pdev,
668                   enum s3c_cpu_type cpu_type)
{
...
struct s3c2410_platform_nand *plat = to_nand_plat(pdev);
720     info->device     = &pdev->dev;
721     info->platform   = plat;
722     info->regs       = ioremap(res->start, size);
723     info->cpu_type   = cpu_type;
...
}

这里struct s3c2410_platform_nand *plat = to_nand_plat(pdev); 这一句为什么可以这样赋值

 16 struct platform_device {                                                                    17     const char  * name;                                                                     18     u32     id;                                                                             19     struct device   dev;                                                                    20     u32     num_resources;                                                                  21     struct resource * resource;                                                             22 };32 struct s3c2410_platform_nand {                                                               33     /* timing information for controller, all times in nanoseconds */34                                                                                             35     int tacls;  /* time for active CLE/ALE to nWE/nOE */                                     36     int twrph0; /* active time for nWE/nOE */                                               37     int twrph1; /* time for release CLE/ALE from nWE/nOE inactive */                        38                                                                                             39     int         nr_sets;                                                                    40     struct s3c2410_nand_set *sets;                                                           41                                                                                             42     void            (*select_chip)(struct s3c2410_nand_set *,                               43                            int chip);                                                       44 };

因为两个结构体前面是一样的。

common-smdk.c和devs.c里面的所有信息,可以得到platform_device的所有配置信息

static struct resource s3c_nand_resource[] = {[0] = {.start = S3C2410_PA_NAND,.end   = S3C2410_PA_NAND + S3C24XX_SZ_NAND - 1,.flags = IORESOURCE_MEM,}
};
struct platform_device s3c_device_nand = {.name          = "s3c2410-nand",.id         = -1,.num_resources    = ARRAY_SIZE(s3c_nand_resource),.resource      = s3c_nand_resource,
};EXPORT_SYMBOL(s3c_device_nand);static struct mtd_partition smdk_default_nand_part[] = {[0] = {.name   = "bootloader",.size   = 0x00040000,.offset   = 0,},[1] = {.name   = "params",.offset = MTDPART_OFS_APPEND,.size   = 0x00020000,},[2] = {.name   = "kernel",.offset = MTDPART_OFS_APPEND,.size   = 0x00200000,},[3] = {.name   = "root",.offset = MTDPART_OFS_APPEND,.size   = MTDPART_SIZ_FULL,}
};static struct s3c2410_nand_set smdk_nand_sets[] = {[0] = {.name     = "NAND",.nr_chips   = 1,.nr_partitions = ARRAY_SIZE(smdk_default_nand_part),.partitions   = smdk_default_nand_part,},
};
static struct s3c2410_platform_nand smdk_nand_info = {.tacls       = 20,.twrph0       = 60,.twrph1       = 20,.nr_sets  = ARRAY_SIZE(smdk_nand_sets),.sets     = smdk_nand_sets,
};static struct platform_device __initdata *smdk_devs[] = {&s3c_device_nand,&led_dev,
#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)&s3c_device_dm9k,
#endif
#ifdef CONFIG_SERIAL_EXTEND_S3C24xx&s3c_device_8250,
#endif
#ifdef CONFIG_TOUCHSCREEN_S3C2410&s3c_device_ts,
#endif
};
s3c_device_nand.dev.platform_data = &smdk_nand_info;
  1. 设置时钟和电平时间
err = s3c2410_nand_inithw(info, pdev);
  1. 填充mtd,和chip部分成员
s3c2410_nand_init_chip(info, nmtd, sets); 577 static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
578                    struct s3c2410_nand_mtd *nmtd,
579                    struct s3c2410_nand_set *set)
580 { ...
84     chip->write_buf    = s3c2410_nand_write_buf;
585     chip->read_buf     = s3c2410_nand_read_buf;
586     chip->select_chip  = s3c2410_nand_select_chip;
587     chip->chip_delay   = 50;
588     chip->priv     = nmtd;
589     chip->options      = 0;
590     chip->controller   = &info->controller;
...
622     chip->IO_ADDR_R = chip->IO_ADDR_W;
623
624     nmtd->info     = info;
625     nmtd->mtd.priv     = chip;
626     nmtd->mtd.owner    = THIS_MODULE;
627     nmtd->set      = set;
...

chip的成员函数,mtd层有默认操作函数,这里需要用户编写的只有部分和硬件操作相关的函数,dev_ready,select_chip,cmd_ctrl需要重新编写。
可以追查函数
cmd_ctrl 调用
nand_scan_ident 调用
nand_set_defaults(chip, busw);

2191     if (!chip->select_chip)
2192         chip->select_chip = nand_select_chip;
2193     if (!chip->read_byte)
2194         chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;
2195     if (!chip->read_word)
2196         chip->read_word = nand_read_word;
2197     if (!chip->block_bad)
2198         chip->block_bad = nand_block_bad;
2199     if (!chip->block_markbad)
2200         chip->block_markbad = nand_default_block_markbad;
2201     if (!chip->write_buf)
2202         chip->write_buf = busw ? nand_write_buf16 : nand_write_buf;
2203     if (!chip->read_buf)
2204         chip->read_buf = busw ? nand_read_buf16 : nand_read_buf;
2205     if (!chip->verify_buf)
2206         chip->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
2207     if (!chip->scan_bbt)
2208         chip->scan_bbt = nand_default_bbt;

默认的select_chip函数

 162 static void nand_select_chip(struct mtd_info *mtd, int chipnr)
163 {
164     struct nand_chip *chip = mtd->priv;
165
166     switch (chipnr) {
167     case -1:
168         chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
169         break;
170     case 0:
171         break;
172
173     default:
174         BUG();
175     }
176 }

可见select_chip在输入为0时,没有操作,需要用户自己构造这个函数
而默认的函数里面没有,dev_ready,cmd_ctrl这两个函数也需要用户进行编写。

  1. nand_scan调用
    这个函数会调用nand_get_flash_type,最终打印nand flash初始化的相关信息。

  2. 设置mtd分区

550 static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
551                       struct s3c2410_nand_mtd *mtd,
552                       struct s3c2410_nand_set *set)
553 {
554     if (set == NULL)
555         return add_mtd_device(&mtd->mtd);
556
557     if (set->nr_partitions > 0 && set->partitions != NULL) {
558         return add_mtd_partitions(&mtd->mtd, set->partitions, set->nr_partitions);
559     }
560
561     return add_mtd_device(&mtd->mtd);
562 }

这里最终也会调用,add_mtd_device

参考的知识博客
nand flash学习
linux flash操作
linux flash 驱动调试
修改mtd分区

nand flash驱动调试学习相关推荐

  1. NAND FLASH学习笔记之MTD下nand flash驱动(一)

    转载请注明:http://blog.csdn.net/wang_zheng_kai/article/details/18988521 有了前面的基础,我们就可以研究MTD下的nand驱动了,我这里用的 ...

  2. NAND FLASH学习笔记之MTD下nand flash驱动(四)

    转载请注明出处:http://blog.csdn.net/wang_zheng_kai 四.Register到MTD子系统 两种注册方式:(我们需要完成的) 1)直接注册整个flash设备(MTD D ...

  3. NAND FLASH学习笔记之MTD下nand flash驱动(六)

    六.驱动层之Flash读操作 MTD对NAND芯片的读写 主要分三部分: A.struct mtd_info中的读写函数,如read,write_oob等,这是MTD原始设备层与FLASH硬件层之间的 ...

  4. linux下nand flash驱动工作原理,Linux下Nand Flash 驱动代码分析

    随着越来越多的平台支持从Nand Flash 中启动,掌握Nand Flash 的驱动编写有着重要的现实意义,由于内核已经完成了大部分的工作,实际工作中大部分工程师对Nand Flash 驱动只是简单 ...

  5. linux驱动编写(nand flash驱动)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 很长一段时间,nand flash都是嵌入式的标配产品.nand flash价格便宜,存储量大, ...

  6. Linux MTD架构下的nand flash驱动详解

    转载自:http://blog.csdn.net/wang_zheng_kai/article/details/18988521 有了前面的基础(Nandflash详解:https://blog.cs ...

  7. nand flash 经典 全面 ------如何编写Linux下Nand Flash驱动

    Crifan Li 摘要 本文先解释了Nand Flash相关的一些名词,再从Flash硬件机制开始,介绍到Nand Flash的常见的物理特性,且深入介绍了Nand Flash的一些高级功能,然后开 ...

  8. 基于VXWORKS的NAND FLASH驱动程序设计

    基于VXWORKS的NAND FLASH驱动程序设计 3162412793@qq.com 技术交流QQ群: 691976956 目前,随着电子技术的不断发展,计算机技术也得到飞速的发展,产生了很多新技 ...

  9. linux用户空间flash驱动,全面掌握Linux驱动框架——字符设备驱动、I2C驱动、总线设备驱动、NAND FLASH驱动...

    原标题:全面掌握Linux驱动框架--字符设备驱动.I2C驱动.总线设备驱动.NAND FLASH驱动 字符设备驱动 哈~ 这几天都在发图,通过这种方式,我们希望能帮大家梳理学过的知识,全局的掌握Li ...

最新文章

  1. 小白巷分享 -- Laravel5的新特性之异常处理
  2. FFmpeg音视频入门-使用FFmpeg读取多媒体文件的信息C++代码实现+详解
  3. TOTP 介绍及基于 C# 的简单实现
  4. xxl-job架构源码解析
  5. 幻想三国android官方版,幻想三国ol官方版下载
  6. matlab shapley函数,合作博弈shapley值讲解.ppt
  7. Python爬虫,4567电影网电影信息爬取,二级页面处理方案
  8. 教你如何修复硬盘及恢复硬盘丢失数据
  9. HarmonyOS:Preferences的封装使用与避坑
  10. Python批量识别PDF文件格式发票信息并生成Excel表格
  11. 视觉SLAM十四讲slambook2/ch3/examples/plotTrajectory.cpp程序报错解决
  12. [前端系列]vue3修改模板变量间隔符
  13. 最新php面试题及答案
  14. #XDOJ 172 构造表达式
  15. 5G主要技术场景与六大关键技术
  16. 学微服务必经之路——Nacos新手入门(下)
  17. python 使用input函数输入两个数字,比较两个数字的大小,并输出较大的数
  18. DSP芯片F2803x系列之PWM模块及高精度PWM使用
  19. 文正机械电子工程专业课_机械电子工程课程编排
  20. MySQL驱动下载,JaveIDEA2022 如何导入mysql数据库驱动

热门文章

  1. 宿舍管理系统-设计数据库
  2. 输出1至100的数字之和;
  3. 决策树算法原理以及决策树规则生成方法
  4. 高斯消元法小总结和瞎总结
  5. JVM(四)_性能监控与调优
  6. 面对大量的用户数据泄露事件,普通用户该如何保护个人的网络信息安全?
  7. [Unityamp;amp;Steam]Steam各种用户数据查询
  8. 欧盟汽车安全机构测评辅助驾驶,特斯拉Autopilot“严重偏科”-1
  9. 基于FPGA的交通灯设计与实现
  10. Base Filtering Engine (BFE)服务无法启动