1. MTD设备与底层驱动的关系

  MTD设备是一种特殊的抽象设备,它用于简化驱动开发。它是底层硬件和上层软件的桥梁,无论对Nand Flash或是Nor Flash,它都提供了统一的框架供上层文件系统使用。对于底层驱动,只需按照各自硬件差异实现MTD中要求的接口即可。
  MTD设备同时实现了Nand驱动的通用访问流程,对于上层文件系统的读、写等访问,MTD设备中都封装了接口,对于Nand驱动的编写,就是根据对应流程填充具体函数即可。

2. MTD结构分析

2.1 MTD中注册的接口函数

  为了能够实现上层文件系统的读写操作,MTD设备为Nand注册了如程序清单 2.1所示的接口。
                  程序清单 2.1 MTD结构

mtd->_erase             = nand_erase;                  /*  Nand擦除操作          */
mtd->_point             = NULL;                         /*  针对片上执行介质        */
mtd->_unpoint           = NULL;                         /*  针对片上执行介质        */
mtd->_read              = nand_read;                   /*  Nand读取操作           */
mtd->_write             = nand_write;                  /*  Nand写入操作           */
mtd->_read_oob          = nand_read_oob;              /*  Nand读取OOB区域      */
mtd->_write_oob         = nand_write_oob;             /*  Nand写入OOB区域      */
mtd->_sync              = nand_sync;                   /*  Nand同步               */
mtd->_lock              = NULL;                         /*  针对支持设备锁的设备    */
mtd->_unlock            = NULL;                         /*  针对支持设备锁的设备    */
mtd->_block_isbad       = nand_block_isbad;           /*  Nand坏块检查           */
mtd->_block_markbad      = nand_block_markbad;        /* Nand坏块标记            */

  对于Nand驱动编写,编程者需要了解nand_erase、nand_read、nand_write等接口的调用流程,才能明白Nand驱动的编程方法。

2.2 Nand驱动接口函数

  对应MTD中的接口,在Nand驱动中最终需实现如程序清单 2.2所示的各类接口函数。
                    程序清单 2.2 nand_chip结构

struct nand_chip {void __iomem *IO_ADDR_R;void __iomem *IO_ADDR_W;uint8_t (*read_byte)(struct mtd_info *mtd);u16      (*read_word)(struct mtd_info *mtd);void     (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);void     (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);   void     (*select_chip)(struct mtd_info *mtd, int chip);      int      (*dev_ready)(struct mtd_info *mtd);void     (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column,int page_addr);int      (*waitfunc)(struct mtd_info *mtd, struct nand_chip *this);void     (*erase_cmd)(struct mtd_info *mtd, int page);int      (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,const uint8_t *buf, int oob_required, int page,int cached, int raw);……struct nand_ecc_ctrl ecc;
}

  nand_chip中的接口并非要求全部实现,对应每一个函数在SylixOS的Base工程中都有默认实现,Nand驱动所做的是将这些接口中与默认实现不对应的单独实现。
  对于Nand中所需的ECC校验操作,本文不做描述,实际调试时可设置为“软件ECC”,待Nand功能实现后,可再修改为实际的硬件ECC操作。

2.3 驱动注册

  以STM32为例,Nand驱动中的nand_chip结构体大致的实现如程序清单 2.3所示。
                  程序清单 2.3 STM32的Nand驱动实现

pNandChip->IO_ADDR_R        = (VOID *)NAND_ADDRESS;
pNandChip->IO_ADDR_W     = (VOID *)NAND_ADDRESS;
pNandChip->cmdfunc               = __nandCommand;           /*  命令操作函数                    */
pNandChip->dev_ready           = __nandDevReady;         /*  判断设备是否准备好        */
pNandChip->select_chip         = __nandChipSelect;         /*  Nand片选操作                   */
pNandChip->waitfunc               = __nandWaitForReady;     /*  判断设备操作是否结束    */
pNandChip->chip_delay          = 50;
pNandChip->ecc.mode            = NAND_ECC_SOFT;

  因为STM32的read_byte、read_word、write_buf等接口与SylixOS中Base实现一致,所以此部分无需在Nand驱动中再次实现。
  对于STM32的Nand驱动,ECC采用了软件ECC方式。

3.流程分析

3.1 复位流程

3.1.1 系统调用流程

  Nand驱动初始时会调用nand_scan接口,nand_scan接口的调用关系如图 3.1所示。最终会调用到Nand驱动实现的cmdfunc函数,并传递NAND_CMD_RESET参数。
                
                  图 3.1 Nand驱动复位流程

3.1.2 Nand驱动实现

  由系统调用关系可知,在__nandCommand中需实现如程序清单 3.1所示的逻辑,HAL_NAND_Reset为STM32具体的复位操作。
                程序清单 3.1 STM32的Nand复位实现

switch (uiCommand) {
case NAND_CMD_RESET:                                /*  nand复位操作                */HAL_NAND_Reset(&_G_handleType);
return;
……
}

3.2 ID读取流程

3.2.1 系统调用流程

  Nand驱动初始时调用nand_scan接口读取Nand的ID,其调用关系如图 3.2所示。
                
                  图 3.2 Nand读取ID流程
  nand_scan会调用到Nand驱动实现的cmdfunc函数,并传递NAND_CMD_READID参数,之后调用read_byte函数,读取到Nand的ID。

3.2.2 Nand驱动实现

  由系统调用关系可知,在__nandCommand中需实现如程序清单 3.2所示的逻辑,根据STM32寄存器说明,实现STM32读取Nand ID的具体操作。
                  程序清单 3.2 STM32的Nand读取ID

switch (uiCommand) {
……
case NAND_CMD_READID:                                /*  nand读取ID操作            */writeb(NAND_CMD_READID,     NAND_ADDRESS | NAND_CMD);writeb(0x00,                NAND_ADDRESS | NAND_ADDR);
return;
……
}

3.3 擦除流程

3.3.1 系统调用流程

  MTD设备擦除时调用nand_erase接口,其调用关系如图 3.3所示,nand_erase会判断是否是单块擦除。
  如果是单块擦除,则调用single_erase_cmd,该接口会调用cmdfunc函数,依次传递NAND_CMD_ERASE1参数和NAND_CMD_ERASE2参数,之后调用waitfunc等待擦除操作完成;
  如果是多块擦除,则调用multi_erase_cmd,该接口会调用四次cmdfunc函数,传递NAND_CMD_ERASE1参数,再调用一次cmdfunc函数,传递NAND_CMD_ERASE2参数,之后调用waitfunc等待擦除操作完成。
        
                  图 3.3 Nand擦除流程

3.3.2 Nand驱动实现

  由系统调用关系可知,在__nandCommand中需实现如程序清单 3.3所示的逻辑,根据STM32寄存器说明,实现STM32擦除Nand的具体操作。
                程序清单 3.3 STM32的Nand擦除操作

switch (uiCommand) {
……
case NAND_CMD_ERASE2:writeb(NAND_CMD_ERASE2,             NAND_ADDRESS | NAND_CMD);
return;
case NAND_CMD_ERASE1:writeb(NAND_CMD_ERASE1,             NAND_ADDRESS | NAND_CMD);writeb((UINT8)(iPagAddr),           NAND_ADDRESS | NAND_ADDR);writeb((UINT8)(iPagAddr >>  8),  NAND_ADDRESS | NAND_ADDR);writeb((UINT8)(iPagAddr >> 16),  NAND_ADDRESS | NAND_ADDR);
return;
……
}

  同时实现__nandWaitForReady接口,如程序清单 3.4所示。
            程序清单 3.4 STM32的Nand等待操作完成操作

static INT  __nandWaitForReady (struct mtd_info  *pMtd, struct nand_chip *this)
{UINT32 uiTime  = 0;while (1) {if (__nandDevReady(pMtd)) {                  /*  如果已经准备好              */break;}uiTime++;if(uiTime >= MAX_WAIT_TIME) {return  (LW_FALSE);                     /*  超时                             */}}return  (LW_TRUE);                              /*  准备好                          */
}

3.4 读取流程

3.4.1 系统调用流程

  MTD设备调用nand_read接口读取Nand的数据,其调用关系如图 3.4所示。
              
                  图 3.4 Nand读取流程
  nand_read中首先会调用cmd_func,传递NAND_CMD_READ0参数,之后调用read_buf实现,实际进行数据读取。

3.4.2 Nand驱动实现

  由系统调用关系可知,在__nandCommand中需实现如程序清单 3.5所示的逻辑,根据STM32寄存器说明,首先对读取Nand的地址进行设置。
              程序清单 3.5 STM32的Nand读取地址设置

switch (uiCommand) {
……
case NAND_CMD_READ0:writeb(NAND_CMD_READ0,              NAND_ADDRESS | NAND_CMD);writeb((UINT8)(iColumn),            NAND_ADDRESS | NAND_ADDR);writeb((UINT8)(iColumn >>   8),      NAND_ADDRESS | NAND_ADDR);writeb((UINT8)(iPagAddr),            NAND_ADDRESS | NAND_ADDR);writeb((UINT8)(iPagAddr >>  8),   NAND_ADDRESS | NAND_ADDR);writeb((UINT8)(iPagAddr >> 16),   NAND_ADDRESS | NAND_ADDR);writeb(NAND_CMD_READSTART,          NAND_ADDRESS | NAND_CMD);__nandWaitRB(1);                                /*  等待RB脚变为高电平          */
return;
……
}

之后调用的read_buf函数,可以使用SylixOS的Base中的默认实现。

3.5 写入流程

3.5.1 系统调用流程

  MTD设备写入时调用nand_write接口写入数据至Nand,其调用关系如图 3.5所示。
                
                  图 3.5 Nand写入流程

3.5.2 Nand驱动流程

  由系统调用关系可知,在__nandCommand中需实现如程序清单 3.6所示的逻辑,根据STM32寄存器说明,首先对写入Nand的地址进行设置。
              程序清单 3.6 STM32的Nand写入地址设置

switch (uiCommand) {
……
case NAND_CMD_SEQIN:writeb(NAND_CMD_WRITE0,             NAND_ADDRESS | NAND_CMD);writeb((UINT8)(iColumn),             NAND_ADDRESS | NAND_ADDR);writeb((UINT8)(iColumn  >>  8),   NAND_ADDRESS | NAND_ADDR);writeb((UINT8)(iPagAddr),           NAND_ADDRESS | NAND_ADDR);writeb((UINT8)(iPagAddr >>  8),  NAND_ADDRESS | NAND_ADDR);writeb((UINT8)(iPagAddr >> 16),  NAND_ADDRESS | NAND_ADDR);bspDelayNs(100);return;
……
}

  之后调用的write_buf函数,可以使用SylixOS的Base中的默认实现。

3.6 读取OOB

3.6.1 系统调用流程

             
                图 3.6 Nand读取OOB流程
  如图 3.6所示,Nand读取OOB的流程与Nand读取操作基本相同,只是cmd_func传递的命令为NAND_CMD_READOOB,所以在Nand驱动中需要进行实现。

3.6.2 Nand驱动流程

  在Nand驱动中的_nandCommand中需要响应NAND_CMD_READOOB操作,如程序清单 3.7所示。
            程序清单 3.7 STM32的Nand读取OOB地址的调整

if (uiCommand == NAND_CMD_READOOB) {            /* 模拟 NAND_CMD_READOOB        */iColumn  += pMtd->writesize;uiCommand = NAND_CMD_READ0;
}

3.7 写入OOB

3.7.1 系统调用流程

  如图 3.7所示,Nand写入OOB的流程与Nand写入操作基本相同,只是在写完数据后会调用cmd_func,传递NAND_CMD_PAGEPROG命令。
               
                  图 3.7 Nand写入OOB流程

3.7.2 Nand驱动流程

  在Nand驱动中的_nandCommand中需要响应NAND_CMD_PAGEPROG操作,如程序清单 3.8所示。
            程序清单 3.8 STM32的Nand写入OOB的页编程命令

switch (uiCommand) {
……
case NAND_CMD_PAGEPROG:writeb(NAND_CMD_PAGEPROG,       NAND_ADDRESS | NAND_CMD);return;
……
}

转载于:https://blog.51cto.com/4102785/2054530

SylixOS中MTD调用底层接口流程分析相关推荐

  1. 码农在使用人脸识别开发套件中的硬件主板如何调用底层接口步骤

    DLT-RK3288C人脸识别开发套件 是由深圳市宁远电子科技有限公司 自主研发推出,基于行业最小最薄的DLT-RK3288C 高性能人脸识别专用主板,融合百度AI 精准的离线人脸识别技术,集算法与软 ...

  2. 【android系统】android系统升级流程分析(一)---recovery模式中进行update包升级流程分析

    今天我们直接来看下android中具体的升级过程是如何的. 升级流程概述 升级的流程图: 升级流程分析 第一步:升级包获取 升级获取可以通过远程下载,也可直接拷贝到指定目录即可. 第二步:准备升级 然 ...

  3. java获取get请求返回_Java中处理调用第三方接口(post/get),该如何处理,返回的数据如何处理...

    条件:1.请求URL:http://ip:port/yypt/*.jsonRequest 2.接口采用http post协议.Content-Type为application/json 调用流程: 第 ...

  4. java第三方接口对接_Java中处理调用第三方接口(post/get),该如何处理,返回的数据如何处理...

    条件:1.请求URL:http://ip:port/yypt/*.jsonRequest 2.接口采用http post协议.Content-Type为application/json 调用流程: 第 ...

  5. pycharm调试如何返回上一步_如何在瑞芯微RK3399开发板上调用底层接口技术调试笔记...

    广东RK3399开发板DLT3399A底层接口文档如何调用方法在DLT3399A板卡正面写有GPIO和UART4_1V8丝印的接口,并看到板子反面对应的引脚gpio丝印,选择相对应的gpio控制节点, ...

  6. Java中Comparable和Comparator接口区别分析

    本文要来详细分析一下Java中Comparable和Comparator接口的区别,两者都有比较的功能,那么究竟有什么区别呢,感兴趣的Java开发者继续看下去吧. Comparable 简介 Comp ...

  7. java调取对方接口_java中如何调用对方接口

    调用对方http接口步骤:URL url = new URL(path); 1.打开和url之间的连接HttpURLConnection conn = (HttpURLConnection) url. ...

  8. java 调用tomcat api,调用servlet接口流程

    使用Servlet接口的整体流程 目前对JavaWeb的理解是:用一次提交过程来表示,当点击一个提交的标签.会将url传到tomcat服务器,在tomcat的配置文件中找到管理javaweb项目的配置 ...

  9. java中如何调用dal接口案例_关于Java:接口的目的

    好吧,我认为接口是一种强制对象实现一定数量功能的方法,而不必使用继承.有点像合同.我半明白他们的意思. 但是,如果界面中的所有内容都是: public interface animal{ void e ...

最新文章

  1. linux内核模块的优缺点
  2. concurrent.futures dataset
  3. Android FFmpeg系列——5 音视频同步播放
  4. 2020 年国外 9 个顶级的 Java 框架,你知道几个?
  5. 源代码管理-SVN自动更新
  6. 《JavaScript 高级程序设计》 7.5 常用模式
  7. Angular 应用的DevDependencies
  8. Ubuntu中配置FTP服务
  9. LwIP移植到FreeRTOS(STM32F107+DP83848)
  10. php函数之----get_magic_quotes_gpc
  11. 悲观锁和乐观锁_浅谈数据库悲观锁和乐观锁
  12. 你喜欢那种类型的收集壁纸?
  13. 创业的一些挫见之第二家公司失败记录
  14. 【Python笔记】列表的用法
  15. 山石网科发布山石云·景产品 安全运维管理进入SaaS模式
  16. jQuery 学习-DOM篇(六):jQuery 替换 DOM 元素
  17. php获得mp3文件总时间,php获得音频文件信息,php获得mp3文件信息
  18. C++的multi_map如何输出所有key值相等的元素
  19. python文件seek_Python文件读取中:f.seek(0)和f.seek(0,0)有什么区别?
  20. 【19调剂】湖南师范大学2019年信息科学与工程学院硕士研究生复试(含调剂)方案...

热门文章

  1. Linux系统通过Squid配置实现代理上网
  2. sftp配置导致ssh连接闪断
  3. ip和nmcli命令的的使用方法
  4. Maven中的pom.properties文件
  5. 文件下载时,IE与FireFox对文件名编码的不同处理! Content-Disposition
  6. lua与python结合_从Python到Lua
  7. 【Python-3.3】字典存储调查问卷
  8. 解决js跨域使用nginx配置问题
  9. 关于多属性查找问题的sphinx解决方案
  10. 解决setInterval计时器不准的问题