目录

1. MTD子系统简介

2. MTD子系统的框架分层

3. MTD子系统重要的数据结构

3.1 struct mtd_info

3.2 struct mtd_part

3.3 struct mtd_partition

3.4 struct nand_chip

4. MTD相关层之间的联系


1. MTD子系统简介

MTD(memory technology device),即内存技术设备,是Linux针对flash设备(nor flash、nand flash等)设计的标准化硬件驱动框架,MTD为了使flash设备的驱动更加简单,因此在上层和硬件之间提供了一个抽象的接口,这样可以在是用不同的flash设备时可以使用相同的API;MTD所有源码位于/drivers/mtd目录下。

2. MTD子系统的框架分层

MTD子系统的框架分层如上图所示,从上到下主要分为四层,分别为设备节点层、MTD设备层、MTD原始设备层以及flash硬件驱动层

设备节点层:可以通过mknod命令在/dev目录下创建MTD设备节点,其中MTD字符设备节点的主设备号为90,MTD块设备节点的主设备号为31,这样就可以通过创建出来的设备节点来访问MTD字符设备和块设备。

MTD设备层:基于MTD原始设备,linux系统可以定义出MTD的字符设备和块设备,其中,在mtdchar.c中实现了MTD字符设备相关接口,在mtdblock.c中实现了MTD块设备相关接口。

MTD原始设备层:MTD原始设备层由两部分构成,一部分是MTD原始设备的通用代码,另一部分是各个特定Flash的数据,比如分区信息;用于描述MTD原始设备的数据结构是mtd_info,它定义了大量的关于MTD的数据和操作函数;原始设备层中重要的文件有两个:一个是mtdcore.c(MTD原始设备接口相关实现 ),另一个是mtdpart.c(MTD分区接口相关实现)。

flash硬件驱动层:flash硬件驱动层的主要作用是初始化flash硬件、对flash设备进行擦除、读、写的具体操作,以及建立从具体的flash设备与MTD原始设备的映射关系;spi nor flash通用驱动位于drivers/mtd/spi-nor/目录下,CFI/jedec通用驱动位于rivers/mtd/chips/目录下,nand flash通用驱动位于drivers/mtd/nand/目录下,nor flash映射关系相关函数位于drivers/mtd/maps/目录下。

3. MTD子系统重要的数据结构

3.1 struct mtd_info

mtd_info结构体用于表示MTD原始设备,它定义了大量的关于MTD的数据和操作函数。

struct mtd_info {u_char type; // MTD类型uint32_t flags; // MTD属性标志uint64_t size;    // MTD设备的总大小uint32_t erasesize; // 擦除单元的大小,对于Nand就是块的大小uint32_t writesize; // 写大小,nor是一个字节,nand是一个页,需确保writesize为1或更大uint32_t writebufsize;uint32_t oobsize;   // 每个块的OOB数据量(例如 16)uint32_t oobavail;  // 每个块的可用OOB字节数/* 默认为0 */unsigned int erasesize_shift;unsigned int writesize_shift;/* 基于erasesize_shift和writesize_shift的掩码,默认为1 */unsigned int erasesize_mask;unsigned int writesize_mask;unsigned int bitflip_threshold;// Kernel-only stuff starts here.const char *name; // 名字int index; // 索引/* OOB布局说明 */const struct mtd_ooblayout_ops *ooblayout;/* NAND配对方案,仅提供给MLC/TLC NAND */const struct mtd_pairing_scheme *pairing;/* ecc步长 */unsigned int ecc_step_size;/* 每个ecc步长的最大可纠正位错误数 */unsigned int ecc_strength;/* 可变擦除区域的数据,通常为1 */int numeraseregions;struct mtd_erase_region_info *eraseregions;/** Do not call via these pointers, use corresponding mtd_*()* wrappers instead.*//* 擦除flash函数 */int (*_erase) (struct mtd_info *mtd, struct erase_info *instr);int (*_point) (struct mtd_info *mtd, loff_t from, size_t len,size_t *retlen, void **virt, resource_size_t *phys);int (*_unpoint) (struct mtd_info *mtd, loff_t from, size_t len);unsigned long (*_get_unmapped_area) (struct mtd_info *mtd,unsigned long len,unsigned long offset,unsigned long flags);/* 读写flash函数 */int (*_read) (struct mtd_info *mtd, loff_t from, size_t len,size_t *retlen, u_char *buf);int (*_write) (struct mtd_info *mtd, loff_t to, size_t len,size_t *retlen, const u_char *buf);int (*_panic_write) (struct mtd_info *mtd, loff_t to, size_t len,size_t *retlen, const u_char *buf);/* 带oob读写flash函数 */int (*_read_oob) (struct mtd_info *mtd, loff_t from,struct mtd_oob_ops *ops);int (*_write_oob) (struct mtd_info *mtd, loff_t to,struct mtd_oob_ops *ops);int (*_get_fact_prot_info) (struct mtd_info *mtd, size_t len,size_t *retlen, struct otp_info *buf);int (*_read_fact_prot_reg) (struct mtd_info *mtd, loff_t from,size_t len, size_t *retlen, u_char *buf);int (*_get_user_prot_info) (struct mtd_info *mtd, size_t len,size_t *retlen, struct otp_info *buf);int (*_read_user_prot_reg) (struct mtd_info *mtd, loff_t from,size_t len, size_t *retlen, u_char *buf);int (*_write_user_prot_reg) (struct mtd_info *mtd, loff_t to,size_t len, size_t *retlen, u_char *buf);int (*_lock_user_prot_reg) (struct mtd_info *mtd, loff_t from,size_t len);int (*_writev) (struct mtd_info *mtd, const struct kvec *vecs,unsigned long count, loff_t to, size_t *retlen);void (*_sync) (struct mtd_info *mtd);int (*_lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);int (*_unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);int (*_is_locked) (struct mtd_info *mtd, loff_t ofs, uint64_t len);/* 坏块管理函数 */int (*_block_isreserved) (struct mtd_info *mtd, loff_t ofs);int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs);int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs);int (*_max_bad_blocks) (struct mtd_info *mtd, loff_t ofs, size_t len);/* 电源管理函数 */int (*_suspend) (struct mtd_info *mtd);void (*_resume) (struct mtd_info *mtd);void (*_reboot) (struct mtd_info *mtd);int (*_get_device) (struct mtd_info *mtd);void (*_put_device) (struct mtd_info *mtd);struct notifier_block reboot_notifier;  /* 重启前的默认模式 *//* ECC状态信息 */struct mtd_ecc_stats ecc_stats;int subpage_sft;void *priv;struct module *owner;struct device dev;int usecount;struct mtd_debug_info dbg;
};

3.2 struct mtd_part

mtd_part结构体用于表示MTD分区,其中包含了 mtd_info结构体用于描述该分区,每一个分区都是被看成一个MTD 原始设备。

struct mtd_part {struct mtd_info mtd; // 分区的详细信息struct mtd_info *parent; // 闪存设备或其他分区uint64_t offset; // 分区的偏移量struct list_head list; // 将mtd_part链成一个链表mtd_partitons
};

3.3 struct mtd_partition

mtd_partition结构体表示分区的信息。

struct mtd_partition {const char *name;      /* 分区名 */const char *const *types;  /* 要使用的解析器的名称(如果有) */uint64_t size;           /* 分区大小 */uint64_t offset;      /* 分区偏移值 */uint32_t mask_flags;     /* 掩码标识 */struct device_node *of_node;
};

3.4 struct nand_chip

MTD使用nand_chip来表示一个NAND FLASH芯片, 该结构体包含了关于Nand Flash的地址信息、读写方法、ECC模式、硬件控制等一系列底层机制。

struct nand_chip {struct mtd_info mtd;void __iomem *IO_ADDR_R; /* 读取闪存设备的8个I/O线的地址 */void __iomem *IO_ADDR_W; /* 写入闪存设备的8条I/O线的地址 *//* 从芯片中读一个字节 */uint8_t (*read_byte)(struct mtd_info *mtd);/* 从芯片中读一个字 */u16 (*read_word)(struct mtd_info *mtd);/* 在低8条I/O线上向芯片写入一个字节 */void (*write_byte)(struct mtd_info *mtd, uint8_t byte);/* 将缓冲区内容写入芯片 */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);/* 使用OOB标记检查是否是坏块 */int (*block_bad)(struct mtd_info *mtd, loff_t ofs);/* 标记坏块 */int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);/* 命令、地址、数据控制函数 */void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl);/* 设备是否就绪 */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);/* 擦除函数 */int (*erase)(struct mtd_info *mtd, int page);/* 扫描坏块表函数 */int (*scan_bbt)(struct mtd_info *mtd);int (*onfi_set_features)(struct mtd_info *mtd, struct nand_chip *chip,int feature_addr, uint8_t *subfeature_para);int (*onfi_get_features)(struct mtd_info *mtd, struct nand_chip *chip,int feature_addr, uint8_t *subfeature_para);int (*setup_read_retry)(struct mtd_info *mtd, int retry_mode);int (*setup_data_interface)(struct mtd_info *mtd, int chipnr,const struct nand_data_interface *conf);int chip_delay;unsigned int options;unsigned int bbt_options;int page_shift;int phys_erase_shift;int bbt_erase_shift;int chip_shift;int numchips;uint64_t chipsize;int pagemask;int pagebuf;unsigned int pagebuf_bitflips;int subpagesize;uint8_t bits_per_cell;uint16_t ecc_strength_ds;uint16_t ecc_step_ds;int onfi_timing_mode_default;int badblockpos;int badblockbits;struct nand_id id;int onfi_version;int jedec_version;union {struct nand_onfi_params onfi_params;struct nand_jedec_params jedec_params;};u16 max_bb_per_die;u32 blocks_per_die;struct nand_data_interface *data_interface;int read_retries;flstate_t state;uint8_t *oob_poi;struct nand_hw_control *controller;struct nand_ecc_ctrl ecc; /* ECC控制结构 */struct nand_buffers *buffers;unsigned long buf_align;struct nand_hw_control hwcontrol;uint8_t *bbt; /* 坏块表指针 */struct nand_bbt_descr *bbt_td; /* 用于闪存查找的坏块表描述符 */struct nand_bbt_descr *bbt_md; /* 坏块表镜像描述符 */struct nand_bbt_descr *badblock_pattern; /* 用于初始坏块扫描的坏块扫描模式 */void *priv; /* 指向私有芯片数据的指针 *//* 包含制造商信息 */struct {const struct nand_manufacturer *desc;void *priv;} manufacturer;
};

4. MTD相关层之间的联系

​​​​​​​

5. 参考文章

Linux MTD系统剖析_lwj103862095的博客-CSDN博客

​​​​​​​Linux内核4.14版本——mtd子系统(1)——简介_风雨兼程8023的博客-CSDN博客_mtd子系统

Linux MTD子系统(1):系统层次分析相关推荐

  1. Linux MTD子系统 _从模型分析到Flash驱动模板

    MTD(Memory Technology Device)即常说的Flash等使用存储芯片的存储设备,MTD子系统对应的是块设备驱动框架中的设备驱动层,可以说,MTD就是针对Flash设备设计的标准化 ...

  2. flash驱动(一):Linux MTD子系统

    转载:Linux MTD子系统 _从模型分析到Flash驱动模板 MTD(Memory Technology Device)即常说的Flash等使用存储芯片的存储设备,MTD子系统对应的是块设备驱动框 ...

  3. Linux MTD子系统学习(二)

    Linux MTD spi-nor驱动分析 3.1 spi-nor设备驱动框架 3.2 spi-nor设备注册 如果希望一个spi设备可以在linux系统下很好的工作,除了写驱动,还要向内核申明和注册 ...

  4. linux中断子系统(基于imx6ul arm32分析)

    0.说明 本文主要针对linux内核中断整个框架进行梳理,针对的是armv7架构,硬件平台是imx6ul,基于arm GIC控制器来分析. GIC是arm公司设计使用的中断控制器,全称Global I ...

  5. Linux V4L2子系统-Video设备框架分析(二)

    1.概述 在V4L2子系统中,Video设备是一个字符设备,设备节点为/dev/videoX,主设备号为81,次设备号范围为0-63.在用户空间,应用可以通过open/close/ioctl/mmap ...

  6. Linux V4L2子系统分析(一)

    1.概述 Linux系统上的Video设备多种多样,如通过Camera Host控制器接口连接的摄像头,通过USB总线连接的摄像头等.为了兼容更多的硬件,Linux内核抽象了V4L2(Video fo ...

  7. linux V4L2子系统——v4l2架构(3)之video_device

    linux V4L2子系统--v4l2架构(3)之video_device 备注:   1. Kernel版本:5.4   2. 使用工具:Source Insight 4.0   3. 参考博客: ...

  8. Linux input子系统分析之一:软件层次

    输入输出是用户和产品交互的手段,因此输入驱动开发在Linux驱动开发中很常见.同时,input子系统的分层架构思想在Linux驱动设计中极具代表性和先进性,因此对Linux input子系统进行深入分 ...

  9. Linux内核4.14版本——Nand子系统(1)——hisi504_nand.c分析

    1. 简介 2. DTS 3. hisi_nfc_probe函数 3.1 获取dts中的资源 3.2 设置nand-chip结构体中必要的字段 3.3 nand_scan_ident扫描识别nand控 ...

最新文章

  1. 不谈面试题,谈谈面试官喜欢见到的特质!
  2. gcc——预处理(预编译),编译,汇编,链接
  3. CentOS-文件操作
  4. linux 时间戳 c语言,c语言中的时间戳和时间格式
  5. 华为OJ: 公共字符串计算
  6. Flink中的Time与Window
  7. C语言 十进制和十六进制相互转换 - C语言零基础入门教程
  8. sqoop导出数据|Hive|HDFS和脚本编写
  9. 关于ip报文校验和一些思考
  10. 【QT】对话框dialog
  11. 读《杀死一只知更鸟To Kill a Mocking Bird》有感
  12. 互联网、云计算之用户服务
  13. APPLE  电脑型号大全
  14. RecyclerView --- 分割线
  15. 自定义EL表达式的函数
  16. 可汗学院金融学(一)
  17. VSCODE: Merge-conflict设置
  18. 如何解决excel表格损坏修复中所遇到的难题
  19. Ⅳ JavaScript函数
  20. 大数据技术与应用实训心得_数据实习心得

热门文章

  1. 手机直播提词器哪个软件好?这两款软件值得收藏
  2. 使用Servlet实现重定向到另一个Servlet文件下载服务端下载
  3. 抖音壁纸表情包小程序搭建,支持达人入驻,源码交付,独立部署,非云开发。
  4. 案例解析:一个完整的项目测试方案流程,应该是怎么的?
  5. VBA窗口乱了如何恢复默认设置
  6. 全站仪坐标计算机公式,全站仪坐标计算公式[].doc
  7. sql语句中的change和modify区别
  8. 非负函数无穷积分的收敛判别法
  9. 大侠是怎样练成的-周昆
  10. 【学术相关】申请审核制下,到双一流大学读博的难度有多大?