NAND flash驱动程序(1)
前言
前面我们已经写过一个块设备驱动程序,用内存来模拟块设备。假如我们想写一个NAND FLASH驱动程序,又应该怎么做呢?我们先看一下kernel代码中别人现成的驱动程序,分析一下流程框架,总结出一个套路,我们就能开始写自己的驱动程序了。
之前写过一个裸板的nand flash程序:NAND FLASH的读操作及原理,可以参考一下。
正文
我参考的是这个驱动程序:drivers\mtd\nand\at91_nand.c。在调用platform_driver_register()平台注册函数后,如果找到device的name同样为"at91_nand",就会调用driver的probe函数(为什么会自动调用probe函数?可以参考我之前写的文章:设备、驱动、总线模型简介)。
static struct platform_driver at91_nand_driver = {.probe = at91_nand_probe,.remove = at91_nand_remove,.driver = {.name = "at91_nand",.owner = THIS_MODULE,},
};static int __init at91_nand_init(void)
{return platform_driver_register(&at91_nand_driver);
}
这里也顺便看一下相关设备资源的注册,其实就是NAND flash的需要设置的寄存器的首地址和结束地址
static struct resource nand_resources[] = {{.start = NAND_BASE,.end = NAND_BASE + SZ_8M - 1,.flags = IORESOURCE_MEM,}
};static struct platform_device at91rm9200_nand_device = {.name = "at91_nand",.id = -1,.dev = {.platform_data = &nand_data,},.resource = nand_resources,.num_resources = ARRAY_SIZE(nand_resources),
};void __init at91_add_device_nand(struct at91_nand_data *data)
{...platform_device_register(&at91rm9200_nand_device);
}
假如已经调用到了probe函数,我们看一下注册函数里面大概做了什么
static int __init at91_nand_probe(struct platform_device *pdev)
{struct at91_nand_host *host;struct mtd_info *mtd;struct nand_chip *nand_chip; //分配nand_chip结构体mtd->priv = nand_chip;mtd = &host->mtd;nand_chip = &host->nand_chip;... //设置nand_chip结构体if (host->board->bus_width_16) /* 16-bit bus width */nand_chip->options |= NAND_BUSWIDTH_16;nand_scan(mtd, 1)add_mtd_partitions(mtd, partitions, num_partitions);
}
由上面的代码可以看出
(1)首先是分配了三个结构体:其中我们重点关注一下mtd_info和nand_chip结构体
(2)然后就是设置nand_chip结构体中的参数等等
(3)最后就是调用了nand_scan()和add_mtd_parttions()函数
下面我们先看一下nand_scan()中具体做了什么。
int nand_scan(struct mtd_info *mtd, int maxchips)
{int ret;...ret = nand_scan_ident(mtd, maxchips);if (!ret)ret = nand_scan_tail(mtd);return ret;
}
继续看一下nand_scan_ident()和nand_scan_tail()里面做了什么
int nand_scan_ident(struct mtd_info *mtd, int maxchips)
{struct nand_chip *chip = mtd->priv;/* Get buswidth to select the correct functions */busw = chip->options & NAND_BUSWIDTH_16; //总线的宽度/* Set the default functions */nand_set_defaults(chip, busw); //设置一些默认的函数,比如选中芯片的函数、发命令函数、读取寄存器值的函数等等/* Read the flash type */type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id);
}
int nand_scan_tail(struct mtd_info *mtd)
{//内容比较多,但是总体就是设置mtd结构体中的读、写、擦除nand flash的操作函数等等mtd->erase = nand_erase;mtd->read = nand_read;mtd->write = nand_write;
}
真正跟到代码里面的话,内容非常多,总结起来就是调用nand_scan()函数,完成一些读、写或者擦除nand flash等等的一些操作函数。设置完后,应该就是注册我们的设置的结构体了,下面继续看一下probe函数最后的add_mtd_partitions()里面的各种调用关系。
add_mtd_partitions(struct mtd_info *master, const struct mtd_partition *parts, int nbparts)//设置slave->mtd,比如读、写、擦除函数等等/* register our partition */add_mtd_device(&slave->mtd); //注册设置过的slave->mtdlist_for_each(this, &mtd_notifiers) {// mtd_notifiers在哪设置?drivers/mtd/mtdchar.c,mtd_blkdev.c调用register_mtd_userstruct mtd_notifier *not = list_entry(this, struct mtd_notifier, list);not->add(mtd);}/* 其中,not->add函数可以分为两部分:* mtd_notify_add -- 字符设备部分* blktrans_notify_add -- 块设备部分*/
先看一下字符设备部分:
static void mtd_notify_add(struct mtd_info* mtd)
{if (!mtd)return;class_device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2),NULL, "mtd%d", mtd->index);class_device_create(mtd_class, NULL,MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),NULL, "mtd%dro", mtd->index);
}
是我们之前写字符设备常见的class_device_create函数,在/sys/class目录创建了相应的设备类目录/sys/class/mtd/
再看一下块设备部分:
static void blktrans_notify_add(struct mtd_info *mtd)list_for_each(this, &blktrans_majors) {struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list);tr->add_mtd(tr, mtd); //调用到了drivers\mtd\mtdblock.c的mtdblock_add_mtd函数}
最后再进到mtdblock_add_mtd()函数里面的各种调用关系
mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)add_mtd_blktrans_dev(dev);//下面就是我们熟悉的,块设备书写的流程了struct gendisk *gd;gd = alloc_disk(1 << tr->part_bits);add_disk(gd);
可以看出来,还是我们熟悉的块设备驱动程序的书写套路。
结语
虽然前面写了很多的内容,而且kernel中代码的流程也非常的复杂,但其实很大一部分是前人为我们抽象出来的一套框架,我们需要做的主要是底层硬件的操作。
在分析流程的时候,我们不难看出,我们要书写一个新的驱动程序,主要就参考probe函数中的部分就好了。下面给出一个别人总结的驱动框架流程图:
NAND flash驱动程序(1)相关推荐
- Linux NAND FLASH驱动程序分析(mini2440)
Linux NAND FLASH驱动程序分析(mini2440) 一.Linux-MTD Subsystem介绍 FLASH在嵌入式系统中是必不可少的,它是bootloader.linux内核和文件系 ...
- MTD 设备驱动 和 NAND Flash 驱动程序分析。
硬件环境: 飞凌OK6410,256MB DDR,2GB NAND Flash. NAND Flash 型号:K9G8G08U9A . 分析源码:Linux 2.6.36.2 内核源码 ...
- 块设备驱动之NAND FLASH驱动程序
转载请注明出处:http://blog.csdn.net/ruoyunliufeng/article/details/25240909 一.框架总结 二.硬件原理 相比于nor flash.我们能够清 ...
- Linux操作系统下 NAND FLASH驱动程序框架
当我们需要在操作系统上读写普通文件的时候,总是需要一层层往下,最终到达硬件相关操作,当然底层设备大多数都是块设备 NAND FLASH就作为一个最底层的块设备. 而我们写驱动,就是要构建硬件与操作系统 ...
- Nand flash驱动的编写与移植
1 Nand flash工作原理 S3C2410板的Nand Flash支持由两部分组成:Nand Flash控制器(集成在S3C2410 CPU)和Nand Flash存储 芯片(K9F12 ...
- 15.NAND FLASH驱动
NAND FLASH 原理以及操作详见:https://blog.csdn.net/qq_16933601/article/details/100001443 一.基本的问题 NAND FLASH是一 ...
- 《Linux驱动:nand flash驱动看这一篇就够了》
文章目录 一,前言 二,硬件电路 2.1 Nand flash相关 2.2 S3c2440相关 2.3 Nand flash 位反转 三,Nand flash驱动框架 四,S3c2440 Nand F ...
- ARM9 2410移植之Nand flash 驱动的编写与移植
1 Nand flash 工作原理 S3C2410 板的Nand Flash 支持由两部分组成:Nand Flash 控制器(集成在S3C2410 CPU)和Nand Flash 存储 芯片(K9F1 ...
- [转]ARM9 2410移植之Nand flash 驱动的编写与移植
1 Nand flash 工作原理 S3C2410 板的Nand Flash 支持由两部分组成:Nand Flash 控制器(集成在S3C2410 CPU)和Nand Flash 存储 芯片(K9F1 ...
最新文章
- Arrays.asList问题
- MySQL跑在CentOS 6 和 7上的性能比较
- modelMapper.map的一个使用例子
- 齐头并进(51Nod-1649)
- 详说 Subversion备份
- PowerDesigner(六)-物理数据模型(PDM逆向工程)
- php sql update 字段a=字段b的信息_企业级PHP求职最全精品面试100问(附答案)
- python multiprocessing 批量下载图片+tqdm
- 威逼司机二选一,是滴滴垄断,还是嘀嗒碰瓷?
- Redis Sentinel 机制与用法(二)
- 人工智能ai应用高管指南_解决AI中的种族偏见:好奇心指南
- FbinstTool最简单制作U盘启动ISO格式(金测)
- ng-alain php,Angular 中后台前端解决方案 - Ng Alain 介绍
- svn怎么执行清理命令_C盘又见红了?一个C盘清理强迫症教你真正有效的解决方法!...
- try{}里有一个return语句,那么紧跟在这个try后的finally{}里的代码会不会被执行
- [刷题]2017百度之星资格赛 - 度度熊与邪恶大魔王
- 多线程(二)互斥锁详解
- win7打开计算机 多窗口,win7电脑无法在一个窗口中打开多个文件夹怎么办?
- Siammask源码demo运行配置
- 挖掘肖特基二极管的作用及其接法