一、MTD系统架构

1.MTD设备体验

FLASH在嵌入式系统中是必不可少的,它是bootloader、linux内核和文件系统的最佳载体。

在Linux内核中引入了MTD子系统为NORFLASH和NAND FLASH设备提供统一的接口,从而使得FLASH驱动的设计大为简化。

  1. cat /proc/mtd

每个分区对应一个块设备

  1. ls -l /dev/mtd*
  2. crw-rw---- 1 0 0 90, 0 Jan 1 00:00 /dev/mtd0
  3. crw-rw---- 1 0 0 90, 1 Jan 1 00:00 /dev/mtd0ro
  4. crw-rw---- 1 0 0 90, 2 Jan 1 00:00 /dev/mtd1
  5. crw-rw---- 1 0 0 90, 3 Jan 1 00:00 /dev/mtd1ro
  6. crw-rw---- 1 0 0 90, 4 Jan 1 00:00 /dev/mtd2
  7. crw-rw---- 1 0 0 90, 5 Jan 1 00:00 /dev/mtd2ro
  8. brw-rw---- 1 0 0 31, 0 Jan 1 00:00 /dev/mtdblock0
  9. brw-rw---- 1 0 0 31, 1 Jan 1 00:00 /dev/mtdblock1
  10. brw-rw---- 1 0 0 31, 2 Jan 1 00:00 /dev/mtdblock2

2.块设备驱动系统架构

二、YAFFS2文件系统应用

1.MTD分区设置
配置linux内核支持mtd,找到mtd接口文件,设置空间大小。
2.Yaffs2文件系统制作
将rootfs格式化生成yaffs文件系统。

  1. /home/win/mkyaffs2image ./rootfs/ rootfs.img

3.Uboot参数设置
在uboot_tq2440\include\configs\TQ2440.h中有uboot的启动配置选项

  1. #define CONFIG_BZIP2
  2. #define CONFIG_LZO
  3. #define CONFIG_LZMA
  4. #define CONFIG_CMD_NAND_YAFFS
  5. #define CONFIG_BOOTARGS "console=ttySAC0 root=/dev/mtdblock3"
  6. #define CONFIG_BOOTCOMMAND "nand read 0x30000000 kernel;bootm 0x30000000"

4.下载烧写与启动

在uboot中用dnw下载

三、Nandflash驱动设计
s3c2410.c/s3c24xx_nand_probe:

  1. static int s3c24xx_nand_probe(struct platform_device *pdev,
  2. enum s3c_cpu_type cpu_type)
  3. {
  4. struct s3c2410_platform_nand *plat = to_nand_plat(pdev);
  5. struct s3c2410_nand_info *info;
  6. struct s3c2410_nand_mtd *nmtd;
  7. struct s3c2410_nand_set *sets;
  8. struct resource *res;
  9. int err = 0;
  10. int size;
  11. int nr_sets;
  12. int setno;
  13. pr_debug("s3c2410_nand_probe(%p)\n", pdev);
  14. info = kmalloc(sizeof(*info), GFP_KERNEL);
  15. if (info == NULL) {
  16. dev_err(&pdev->dev, "no memory for flash info\n");
  17. err = -ENOMEM;
  18. goto exit_error;
  19. }
  20. memset(info, 0, sizeof(*info));
  21. platform_set_drvdata(pdev, info);
  22. spin_lock_init(&info->controller.lock);
  23. init_waitqueue_head(&info->controller.wq);
  24. /* get the clock source and enable it */
  25. info->clk = clk_get(&pdev->dev, "nand");                                  //获取时钟,并使能
  26. if (IS_ERR(info->clk)) {
  27. dev_err(&pdev->dev, "failed to get clock\n");
  28. err = -ENOENT;
  29. goto exit_error;
  30. }
  31. clk_enable(info->clk);
  32. /* allocate and map the resource */
  33. /* currently we assume we have the one resource */
  34. res = pdev->resource;
  35. size = res->end - res->start + 1;
  36. info->area = request_mem_region(res->start, size, pdev->name);                         //地址转换
  37. if (info->area == NULL) {
  38. dev_err(&pdev->dev, "cannot reserve register region\n");
  39. err = -ENOENT;
  40. goto exit_error;
  41. }
  42. info->device = &pdev->dev;
  43. info->platform = plat;
  44. info->regs = ioremap(res->start, size);
  45. info->cpu_type = cpu_type;
  46. if (info->regs == NULL) {
  47. dev_err(&pdev->dev, "cannot reserve register region\n");
  48. err = -EIO;
  49. goto exit_error;
  50. }
  51. dev_dbg(&pdev->dev, "mapped registers at %p\n", info->regs);
  52. /* initialise the hardware */
  53. err = s3c2410_nand_inithw(info);                                                        //初始化硬件
  54. if (err != 0)
  55. goto exit_error;
  56. sets = (plat != NULL) ? plat->sets : NULL;
  57. nr_sets = (plat != NULL) ? plat->nr_sets : 1;
  58. info->mtd_count = nr_sets;
  59. /* allocate our information */
  60. size = nr_sets * sizeof(*info->mtds);
  61. info->mtds = kmalloc(size, GFP_KERNEL);
  62. if (info->mtds == NULL) {
  63. dev_err(&pdev->dev, "failed to allocate mtd storage\n");
  64. err = -ENOMEM;
  65. goto exit_error;
  66. }
  67. memset(info->mtds, 0, size);
  68. /* initialise all possible chips */
  69. nmtd = info->mtds;
  70. for (setno = 0; setno < nr_sets; setno++, nmtd++) {
  71. pr_debug("initialising set %d (%p, info %p)\n", setno, nmtd, info);
  72. s3c2410_nand_init_chip(info, nmtd, sets);                                               //里面有校验nandflash
  73. nmtd->scan_res = nand_scan_ident(&nmtd->mtd,                                            //搜索nandflash
  74. (sets) ? sets->nr_chips : 1);
  75. if (nmtd->scan_res == 0) {
  76. s3c2410_nand_update_chip(info, nmtd);
  77. nand_scan_tail(&nmtd->mtd);
  78. s3c2410_nand_add_partition(info, nmtd, sets);                                        //注册分区信息
  79. }
  80. if (sets != NULL)
  81. sets++;
  82. }
  83. err = s3c2410_nand_cpufreq_register(info);
  84. if (err < 0) {
  85. dev_err(&pdev->dev, "failed to init cpufreq support\n");
  86. goto exit_error;
  87. }
  88. if (allow_clk_stop(info)) {
  89. dev_info(&pdev->dev, "clock idle support enabled\n");
  90. clk_disable(info->clk);
  91. }
  92. pr_debug("initialised ok\n");
  93. return 0;
  94. exit_error:
  95. s3c2410_nand_remove(pdev);
  96. if (err == 0)
  97. err = -EINVAL;
  98. return err;
  99. }

MTD通用驱动部分nand_base.c(nand_read:

  1. static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
  2. size_t *retlen, uint8_t *buf)
  3. {
  4. struct nand_chip *chip = mtd->priv;
  5. int ret;
  6. /* Do not allow reads past end of device */
  7. if ((from + len) > mtd->size)
  8. return -EINVAL;
  9. if (!len)
  10. return 0;
  11. nand_get_device(chip, mtd, FL_READING);
  12. chip->ops.len = len;
  13. chip->ops.datbuf = buf;
  14. chip->ops.oobbuf = NULL;
  15. ret = nand_do_read_ops(mtd, from, &chip->ops);                                       //进行读操作的代码
  16. *retlen = chip->ops.retlen;
  17. nand_release_device(mtd);
  18. return ret;
  19. }

nand_do_read_ops:

  1. /**
  2. * nand_do_read_ops - [Internal] Read data with ECC
  3. *
  4. * @mtd:    MTD device structure
  5. * @from:    offset to read from
  6. * @ops:    oob ops structure
  7. *
  8. * Internal function. Called with chip held.
  9. */
  10. static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
  11. struct mtd_oob_ops *ops)
  12. {
  13. int chipnr, page, realpage, col, bytes, aligned;
  14. struct nand_chip *chip = mtd->priv;
  15. struct mtd_ecc_stats stats;
  16. int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
  17. int sndcmd = 1;
  18. int ret = 0;
  19. uint32_t readlen = ops->len;
  20. uint32_t oobreadlen = ops->ooblen;
  21. uint8_t *bufpoi, *oob, *buf;
  22. stats = mtd->ecc_stats;
  23. chipnr = (int)(from >> chip->chip_shift);
  24. chip->select_chip(mtd, chipnr);
  25. realpage = (int)(from >> chip->page_shift);
  26. page = realpage & chip->pagemask;
  27. col = (int)(from & (mtd->writesize - 1));
  28. buf = ops->datbuf;
  29. oob = ops->oobbuf;
  30. while(1) {
  31. bytes = min(mtd->writesize - col, readlen);
  32. aligned = (bytes == mtd->writesize);
  33. /* Is the current page in the buffer ? */
  34. if (realpage != chip->pagebuf || oob) {
  35. bufpoi = aligned ? buf : chip->buffers->databuf;
  36. if (likely(sndcmd)) {
  37. chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);                                              //实际对应了nand_command_lp,cmd命令是0
  38. sndcmd = 0;
  39. }
  40. .........
  41. }

nand_command_lp:

  1. static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
  2. int column, int page_addr)
  3. {
  4. register struct nand_chip *chip = mtd->priv;
  5. /* Emulate NAND_CMD_READOOB */
  6. if (command == NAND_CMD_READOOB) {
  7. column += mtd->writesize;
  8. command = NAND_CMD_READ0;
  9. }
  10. /* Command latch cycle */
  11. chip->cmd_ctrl(mtd, command & 0xff,
  12. NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);                                   //cmd_ctrl来源于底层驱动,在s3c2410_nand_init_chip中赋值了。
  13. .......
  14. }

s3c2410_nand_hwcontrol:

  1. /* s3c2410_nand_hwcontrol
  2. *
  3. * Issue command and address cycles to the chip
  4. */
  5. static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd,
  6. unsigned int ctrl)
  7. {
  8. struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
  9. if (cmd == NAND_CMD_NONE)
  10. return;
  11. if (ctrl & NAND_CLE)
  12. writeb(cmd, info->regs + S3C2410_NFCMD);                                     //往NFCONT寄存器中写入cmd,cmd来自于nand_command,往上回溯为nand_read.其实就是发送了命令0x00
  13. else
  14. writeb(cmd, info->regs + S3C2410_NFADDR);
  15. }

继续回到nand_command_lp:

  1. ...............
  2. if (column != -1 || page_addr != -1) {
  3. int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE;
  4. /* Serially input address */
  5. if (column != -1) {
  6. /* Adjust columns for 16 bit buswidth */
  7. if (chip->options & NAND_BUSWIDTH_16)
  8. column >>= 1;
  9. chip->cmd_ctrl(mtd, column, ctrl);                                   //紧接着发送列地址
  10. ctrl &= ~NAND_CTRL_CHANGE;
  11. chip->cmd_ctrl(mtd, column >> 8, ctrl);
  12. }
  13. if (page_addr != -1) {
  14. chip->cmd_ctrl(mtd, page_addr, ctrl);                                //发送行地址
  15. chip->cmd_ctrl(mtd, page_addr >> 8,
  16. NAND_NCE | NAND_ALE);
  17. /* One more address cycle for devices > 128MiB */
  18. if (chip->chipsize > (128 << 20))
  19. chip->cmd_ctrl(mtd, page_addr >> 16,
  20. NAND_NCE | NAND_ALE);
  21. }
  22. }
  23. chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
  24. /*
  25. * program and erase have their own busy handlers
  26. * status, sequential in, and deplete1 need no delay
  27. */
  28. switch (command) {
  29. case NAND_CMD_CACHEDPROG:
  30. case NAND_CMD_PAGEPROG:
  31. case NAND_CMD_ERASE1:
  32. case NAND_CMD_ERASE2:
  33. case NAND_CMD_SEQIN:
  34. case NAND_CMD_RNDIN:
  35. case NAND_CMD_STATUS:
  36. case NAND_CMD_DEPLETE1:
  37. return;
  38. /*
  39. * read error status commands require only a short delay
  40. */
  41. case NAND_CMD_STATUS_ERROR:
  42. case NAND_CMD_STATUS_ERROR0:
  43. case NAND_CMD_STATUS_ERROR1:
  44. case NAND_CMD_STATUS_ERROR2:
  45. case NAND_CMD_STATUS_ERROR3:
  46. udelay(chip->chip_delay);
  47. return;
  48. case NAND_CMD_RESET:
  49. if (chip->dev_ready)
  50. break;
  51. udelay(chip->chip_delay);
  52. chip->cmd_ctrl(mtd, NAND_CMD_STATUS,
  53. NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
  54. chip->cmd_ctrl(mtd, NAND_CMD_NONE,
  55. NAND_NCE | NAND_CTRL_CHANGE);
  56. while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ;
  57. return;
  58. case NAND_CMD_RNDOUT:
  59. /* No ready / busy check necessary */
  60. chip->cmd_ctrl(mtd, NAND_CMD_RNDOUTSTART,
  61. NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
  62. chip->cmd_ctrl(mtd, NAND_CMD_NONE,
  63. NAND_NCE | NAND_CTRL_CHANGE);
  64. return;
  65. case NAND_CMD_READ0:
  66. chip->cmd_ctrl(mtd, NAND_CMD_READSTART,                                                    //这里发送了0x30命令
  67. NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
  68. chip->cmd_ctrl(mtd, NAND_CMD_NONE,
  69. NAND_NCE | NAND_CTRL_CHANGE);
  70. /* This applies to read commands */
  71. default:
  72. /*
  73. * If we don't have access to the busy pin, we apply the given
  74. * command delay
  75. */
  76. if (!chip->dev_ready) {
  77. udelay(chip->chip_delay);
  78. return;
  79. }
  80. }
  81. /* Apply this short delay always to ensure that we do wait tWB in
  82. * any case on any machine. */
  83. ndelay(100);
  84. nand_wait_ready(mtd);                                                                          //wait等待
  85. }

<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>

阅读(38) | 评论(0) | 转发(0) |

0

上一篇:块设备驱动系统架构和简单设计

下一篇:I2C学习

相关热门文章
  • SHTML是什么_SSI有什么用...
  • 查看linux中某个端口(port)...
  • 卡尔曼滤波的原理说明...
  • shell中字符串操作
  • 关于java中的“错误:找不到或...
给主人留下些什么吧!~~
评论热议

MTD系统架构和yaffs2使用、Nandflash驱动设计相关推荐

  1. linux 内核 scsi底层驱动程序,Linux系统下基于SCST的SCSI_Target驱动设计.doc

    Linux系统下基于SCST的SCSI target驱动设计 摘要 随着信息数字化的深入发展,数据存储的需求日益增长.存储虚拟化带给我们最直接的益处就是,提高存储利用率,降低成本,简化存储管理,而基于 ...

  2. 软考高级系统架构设计师:响应式Web设计和主从复制机制的好处

    软考高级系统架构设计师:响应式Web设计和主从复制机制的好处 一.响应式Web设计 二.主动复制机制的好处 一.响应式Web设计 响应式Web设计目的是让内容布局能随用户使用的显示器不同而变化. 两个 ...

  3. 国内最缺的架构实践,DDD领域驱动设计排第一!

    前段时间,参加了一场闭门技术交流会,讨论的热点是微服务,话题集中在微服务架构拆分到底应该拆多细. 有微服务的地方就有 DDD(领域驱动设计),不过即便是专业的技术交流会,也没人能给 DDD 的价值下个 ...

  4. 架构之路_DDD领域驱动设计总结

    推荐书籍:领域驱动设计 - 软件核心复杂性应对之道 - Eric Evans. 视频教程:DDD 微服务落地实战视频教程 一.DDD基础名词概念 领域驱动设计(DDD),它是针对复杂系统设计的一套整软 ...

  5. 软考高级-系统架构师-第五章软件架构设计

    本篇博文目录: 一.软件架构设计 1.软件架构的定义 2.体系结构设计(SA)与生命周期 (1) 需求分析阶段 (2) 设计阶段 (3) 实现阶段 (4) 构建组装阶段 (5) 部署阶段 (6) 后开 ...

  6. 系统架构师论文-财务数据仓库系统的设计与实现

    财务数据仓库系统的设计与实现 [摘要] 近年来,数据仓库技术在信息系统的建设中得到了广泛应用,有效地为决策提供了支持.2004年6月,本人所在单位组织开发了财务管理决策系统,该系统主要是使高层领导掌握 ...

  7. 爽,字节架构师DDD(领域驱动设计)巅峰之作,拆解业务代码真好用

    前 言 至少20年前,一些顶尖的软件设计人员就已经认识到领域建模和设计的重要性,但令人惊讶的是,这么长时间以来几乎没有人写出点儿什么,告诉大家应该做哪些工作或如何去做.尽管这些工作还没有被清楚地表述出 ...

  8. 深入理解Tomcat和Jetty源码之第四篇tomcat系统架构上:容器是如何设计的

    今天来介绍一下Tomcat的容器机制: 1.Tomcat的四种容器 2.容器示意图 3.责任链模式介绍 4.Tomcat如何确定请求是哪个Wrapper处理的 5.Tomcat的Context和ser ...

  9. 深入理解Tomcat和Jetty源码之第三篇tomcat系统架构上:连接器是如何设计的

    我们都知道Tomcat服务器是包括连接器和容器,​那他们内部具体是怎么实现的呢?今天让我们一起来学习一下~ 1.tomcat基础知识 2.tomcat和service的关系 3.tomcat的详细介绍 ...

最新文章

  1. python 网络通讯 plc_PLC与PC网络通信实验
  2. Mahout分步式程序开发 聚类Kmeans
  3. ZOJ - 3777 Problem Arrangement(状压dp)
  4. MFC中获取命令行参数的几种方法
  5. 使用mysql自带工具mysqlslap测试数据库性能
  6. Web前端笔记-解决NicSroll使用后页面跳动(每次刷新或进入跳动一下然后正常)问题
  7. PULSE:一种基于隐式空间的图像超分辨率算法
  8. CCF NOI1032 菱形
  9. 我是如何成为算法工程师的,超详细的学习路线
  10. Mac OS X中Apache开启ssl
  11. mysql数据库编程第六章试题_2016计算机二级MySQL数据库试题及答案
  12. 尚学堂马士兵Oracle教程 笔记
  13. <<道 德 经>>------老子
  14. box-shadow单边阴影设置
  15. 总结AUTOCAD快捷键,持续更新~
  16. 解读《大话西游之大圣娶亲》
  17. Word目录:【同一篇文档设置多个独立目录】详细过程
  18. 解决Gradle‘s dependency cache may be corrupt (this sometimes occurs after a network connection timeout
  19. 实验楼linux命令,GitHub - encorechow/linux-command: Linux命令大全搜索工具,内容包含Linux命令手册、详解、学习、搜集。...
  20. Java——OOP三大特性之封装性(Encapsulation)通俗详细

热门文章

  1. hdmi接口有什么用_(转)电视上各种各样的接口有什么用?你能知道几个?
  2. 我,94年山西人,矿山地质专业,自学软件当程序员,加班到窒息
  3. 使用selenium操控浏览器爬取QQ音乐
  4. Model-Agnostic Meta-Learning for Fast Adaptation of Deep Networks阅读笔记
  5. ExiD、InD、HighD轨迹数据
  6. 树莓派4B系统一键安装opencv,再也不要用编译安装啦!(支持buster、bullseye)
  7. 【日常Exception】第二十四回:nested exception is java.lang.NoClassDefFoundError: redis/clients/jedis/util/Pool
  8. dev c++怎么设置断点_斑马进度计划软件可以检查计划中是否存在逻辑断点和错误逻辑关系...
  9. oracle报错1455,oracle_1455_错误解决办法
  10. Tesla Autopilot技术架构整理(引用自EatElephant)