1. 如何编写linux下的 Nand flash驱动
Bare NAND chips:裸片,单独的nand 芯片 SmartMediaCards: =裸片+一层薄塑料,常用于数码相机和MP3播放器中。之所以称smart,是由于其软件smart,而不是硬件本身有啥smart之处。^_^ DiskOnChip:裸片+glue logic,glue logic=硬件ECC产生器+用于静态的nand 芯片控制的寄存器+直接访问一小片地址窗口,那块地址中包含了引导代码的stub桩,其可以从nand flash中拷贝真正的引导代码。 Nand flash的操作,和其他一些常见的设备,如硬盘等,不同,其有自己特殊的方式。 其特殊就在于: Nand flash的最小单位是页page,而不是其他很多设备所说的位bit。 写入数据之前必须先进行擦除erase操作 写的时候,最小单位是页page,对也进行写操作,也称作“页编程”,page programming 擦除的最小单位是块block 由于物理特性,容易出错,所以无论是读还是写,都要采取检测和校验,即EDC。 nand flash出厂时候,就有一定坏的块block,成为换块,并且做了一定标记。 nand flash中有个额外的空间,叫做spare area/oob!
2. linux nor flash驱动如何加载为什么系统中没有mtdcore.c文件
这个文件在内核源码driver/mtd目录下面,要考虑到你的调试内核是否有编译mtd驱动,或者以模块方式编译的mtdcore而没有加载。
你是用insmod方式加载ko并不能解决模块依赖问题的。
3. 如何编写Linux下Nand Flash驱动
1.硬件方面:
【Flash的种类】
Flash主要分nand flash和nor flash
除了网上最流行的这个解释之外:
NAND和NOR的比较
我再多说几句,nor的成本相对高,比较适合应用于存储少量的代码。
Nand flash相对成本低,因此可以用来存储大量的数据,其在嵌入式系统中的作用,相当于PC上的硬盘,用于存储大量数据。
Nor flash,有类似于dram之类的地址总线,因此可以直接和CPU相连,CPU可以直接通过地址总线对nor flash进行访问,而nand flash没有这类的总线,只有IO接口,只能通过IO接口发送命令和地址,对nand flash内部数据进行访问。相比之下,nor flash就像是并行访问,nand flash就是串行访问,所以相对来说,前者的速度更快些。
2.软件方面:
Linux驱动原理
具体内部很多实现,已经包含在drivers/mtd/nand/nand_base.c中了
【nand flash驱动加载识别nand类型过程】
在驱动加载的时候,会去调用:
nand_get_flash_type()
其中,就会对nand的类型和其他相关参数进行检查。
1) 选中对应设备,如果此时只有一个nand 芯片,则此步可以省略
/* Select the device */
chip->select_chip(mtd, 0);
x
2) 发读命令,去读取设备类型代码
/* Send the command for reading device ID */
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
3) 判断是哪个厂商的,哪个类型的flash
/* Read manufacturer and device IDs */
*maf_id = chip->read_byte(mtd);
dev_id = chip->read_byte(mtd);
4) 在事先已经定义好的nand flash类型中查找属于何种厂商和型号
/* Lookup the flash id */
for (i = 0; nand_flash_ids[i].name != NULL; i++) {
if (dev_id == nand_flash_ids[i].id) {
type = &nand_flash_ids[i];
break;
}
}
5) 继续判断具体nand flash的各个参数,包括
芯片信息,Pagesize页大小,oobsize即oob的大小,blocksize块大小,buswidth总线宽度是8位还是16位。
如果页大小不是之前老的nand的512B,而是新的nand的2K或更大,则后面对应的发送给nand flash命令的的时候,调用的函数就由nand_command()变成nand_command_lp()了。
后者主要比前者多一发个命令:
chip->cmd_ctrl(mtd, column >> 8, ctrl);
即,多发一个列地址命令。
因为大页面(>2KB)的寻址需要2次column,而小页面(512B)只需要1次的列地址。
具体可以参考nand flash的datasheet。
6) 接着会做一些其他初始化操作,包括最后调用nand_set_defaults()去实现的默认函数的挂载,如果你的nand flash驱动没有实现的话,就是挂载默认的了。
【模块加载原理】
这个内容太大,此处只是简单说说。
驱动加载的功能主要是probe函数实现的,主要去识别设备的类型和各个参数,并且为设备的使用进行正常的初始化。
对应卸载时候执行的remove函数,施放对应的,之前申请的一些资源。
【MTD设备】
在Linux下,将nand Flash等设备归属到MTD设备下进行统一管理。
Mtd,即memory technology deveice,即将nand看出是存储设备来管理。
之所以会这么说和这么做,是因为前面提高的nand flash和普通硬盘等设备的特殊性:
IO接口,最小单位是页,写前需擦除等,导致了,不能像平常对待硬盘等操作一样去操作nand flash,只能采取一些特殊方法,这就诞生了mtd设备的统一抽象层,将nand flash,nor flash和其他类型的flash等设备,统一抽象成mtd设备来管理,根据这些设备的特点,上层实现了常见的操作函数封装,底层具体的内部实现,就需要驱动设计者自己来实现了。
4. 如何编写linux下nand flash驱动
Linux驱动原理
具体内部很多实现,已经包含在drivers/mtd/nand/nand_base.c中了
【nand flash驱动加载识别nand类型过程】
在驱动加载的时候,会去调用:
nand_get_flash_type()
其中,就会对nand的类型和其他相关参数进行检查。
1) 选中对应设备,如果此时只有一个nand 芯片,则此步可以省略
/* Select the device */
chip->select_chip(mtd, 0);
x
2) 发读命令,去读取设备类型代码
/* Send the command for reading device ID */
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
3) 判断是哪个厂商的,哪个类型的flash
/* Read manufacturer and device IDs */
*maf_id = chip->read_byte(mtd);
dev_id = chip->read_byte(mtd);
4) 在事先已经定义好的nand flash类型中查找属于何种厂商和型号
/* Lookup the flash id */
for (i = 0; nand_flash_ids[i].name != NULL; i++) {
if (dev_id == nand_flash_ids[i].id) {
type = &nand_flash_ids[i];
break;
}
}
5) 继续判断具体nand flash的各个参数,包括
芯片信息,Pagesize页大小,oobsize即oob的大小,blocksize块大小,buswidth总线宽度是8位还是16位。
如果页大小不是之前老的nand的512B,而是新的nand的2K或更大,则后面对应的发送给nand flash命令的的时候,调用的函数就由nand_command()变成nand_command_lp()了。
后者主要比前者多一发个命令:
chip->cmd_ctrl(mtd, column >> 8, ctrl);
即,多发一个列地址命令。
因为大页面(>2KB)的寻址需要2次column,而小页面(512B)只需要1次的列地址。
具体可以参考nand flash的datasheet。
6) 接着会做一些其他初始化操作,包括最后调用nand_set_defaults()去实现的默认函数的挂载,如果你的nand flash驱动没有实现的话,就是挂载默认的了。
【模块加载原理】
这个内容太大,此处只是简单说说。
驱动加载的功能主要是probe函数实现的,主要去识别设备的类型和各个参数,并且为设备的使用进行正常的初始化。
对应卸载时候执行的remove函数,施放对应的,之前申请的一些资源。
【MTD设备】
在Linux下,将nand Flash等设备归属到MTD设备下进行统一管理。
Mtd,即memory technology deveice,即将nand看出是存储设备来管理。
之所以会这么说和这么做,是因为前面提高的nand flash和普通硬盘等设备的特殊性:
IO接口,最小单位是页,写前需擦除等,导致了,不能像平常对待硬盘等操作一样去操作nand flash,只能采取一些特殊方法,这就诞生了mtd设备的统一抽象层,将nand flash,nor flash和其他类型的flash等设备,统一抽象成mtd设备来管理,根据这些设备的特点,上层实现了常见的操作函数封装,底层具体的内部实现,就需要驱动设计者自己来实现了。
1. 了解硬件的nand flash的各个参数和工作原理
具体参考nand flash的datasheet,主要包括,自己nand flash的厂商,型号等。
Nand flash的页大小,oob大小,块大小,位宽8bit还是16bit。
工作原理,上面已经做了一定描述,不清楚的,可以参考datasheet,多看看,就会明白很多。
2. 按照linux下驱动编写规范编写nand flash驱动,
可以参考其他已经有的驱动,比如内核源码中已经有的
drivers/mtd/nand/s3c2410.c
就是个很好的例子。
自己以其为模板,实现自己板子的nand flash驱动。
其实主要工作就是,实现
static struct platform_driver s3c2410_nand_driver = {
.probe = s3c2410_nand_probe,
.remove = s3c2410_nand_remove,
.suspend = s3c24xx_nand_suspend,
.resume = s3c24xx_nand_resume,
.driver = {
.name = "s3c2410-nand",
.owner = THIS_MODULE,
},
};
中的
XXX_nand_probe函数
XXX_nand_remove函数
XXX_nand_enable_hwecc,如果支持硬件ecc的话。
对nand flash的读写,这两个函数,实现了对nand的具体操作。
【Linux下Nand Flash驱动编写简单步骤】
软件和硬件知识,都已经了解的话,由于上层的linux的 mtd框架中,已经完全封装好了,对nand flash的write page,write oob等相关函数的实现,那么剩下的只是相对来说已经是很少量的,关于nand 驱动具体内部操作方面的工作:
1.初始化
先是在nand 芯片初始化的时候,对其
XXX_nand_init_chip()
给对应的芯片chip赋给对应的
XXX_nand_read_buf和XXX_nand_write_buf等函数:
chip->cmd_ctrl = XXX_nand_hwcontrol;
chip->dev_ready = XXX_nand_devready;
chip->read_buf = XXX_nand_read_buf;
chip->write_buf = XXX_nand_write_buf;
以实现后续的对nand芯片的操作。
然后根据ecc类型,赋给对应的ecc的校验与纠错函数:
chip->ecc.hwctl = XXX_nand_enable_hwecc;
chip->ecc.calculate = XXX _nand_calculate_ecc;
3. 实现上面提到的对应的各个函数,关于如何实现,参考一下其他nand驱动,就会理解很多了。
4. 驱动测试,参考具体的 ldd3(Linux Device Driver version 3)的测试相关部分内容。
转载仅供参考,版权属于原作者。祝你愉快,满意请采纳哦
5. 求问linux nor flash驱动编程过程中add_mtd_partitions和del_mtd_partitions怎么用
add_mtd_partitions函数,add_mtd_partitions()会对每一个新建分区建立一个新的mtd_part 结构体,将其加入mtd_
partitions中,并调用add_mtd_device()将此分区作为MTD设备加入mtd_table。成功时返回0,如果分配mtd_part时内存不足,则返回-ENOMEM。
1、在说这个函数前,先说下,与这有关的结构体struct mtd_part和struct
mtd_partition结构体,如下所示:
mtd_part结构体用于描述分区,其mtd_info结构体成员用于描述本分区
/* Our partition node structure */
struct
mtd_part {
struct mtd_info mtd;
分区的信息(大部分由其master决定
struct mtd_info
*master; 该分区的主分区
u_int32_t offset;
该分区的偏移地址
int index; 分区号
struct list_head list;
int registered;
};
struct mtd_partition {
char *name; /* identifier string */ 标识字符串
u_int32_t size;/* partition size */ 分区大小
u_int32_t offset;/* offset within the master MTD
space */ 主MTD空间内的偏移
u_int32_t
mask_flags;/* master MTD flags to mask out
for this partition */
struct
nand_ecclayout *ecclayout;/* out of band
layout for this partition (NAND only)*/
struct mtd_info **mtdp;/* pointer to store the MTD object
*/
};
为了更明白我们以6410中的定义:
struct mtd_partition s3c_partition_info[] =
{
{
.name =
"Bootloader",
.offset =
0,
.size =
(256*SZ_1K),
.mask_flags = MTD_CAP_NANDFLASH,
},
{
.name = "Kernel",
.offset = (256*SZ_1K),
.size = (4*SZ_1M) - (256*SZ_1K),
.mask_flags =
MTD_CAP_NANDFLASH,
},
#if
defined(CONFIG_SPLIT_ROOT_FILESYSTEM)
{
.name = "Rootfs",
.offset = (4*SZ_1M),
//
.size = (512*SZ_1M),//(48*SZ_1M),
.size =
(80*SZ_1M),//(48*SZ_1M),
},
#endif
{
.name = "File System",
.offset = MTDPART_OFS_APPEND,
.size = MTDPART_SIZ_FULL,
}
};
struct s3c_nand_mtd_info s3c_nand_mtd_part_info = {
.chip_nr = 1,
.mtd_part_nr =
ARRAY_SIZE(s3c_partition_info),
.partition
= s3c_partition_info,
};
2、下面来看add_mtd_partitions函数,源码如下:
/*
* This function, given a master MTD object and a
partition table, creates
* and registers slave MTD objects which are bound
to the master according to
* the partition definitions.
* (Q:
should we register the master MTD object as well?)
*/
int
add_mtd_partitions(struct mtd_info *master,
const struct
mtd_partition *parts,
int
nbparts)
{
struct mtd_part
*slave;
u_int32_t cur_offset = 0;
int i;
printk(KERN_NOTICE "Creating
%d MTD partitions on \"%s\":\n", nbparts, master->name);
for (i = 0; i
< nbparts; i++) { 主要就是这个循环体,应该是分别添加每个struct
mtd_partition结构
slave =
add_one_partition(master, parts + i, i, cur_offset);
if (!slave)
return -ENOMEM;
cur_offset = slave->offset
+ slave->mtd.size;
}
return
0;
}
6. 如何编写Linux下Nand Flash驱动
摘录的别人心得
【Linux下nand flash驱动编写步骤简介】
1. 了解硬件的nand
flash的各个参数和工作原理
具体参考nand flash的datasheet,主要包括,自己nand
flash的厂商,型号等。
Nand flash的页大小,oob大小,块大小,位宽8bit还是16bit。
工作原理,上面已经做了一定描述,不清楚的,可以参考datasheet,多看看,就会明白很多。
2. 按照linux下驱动编写规范编写nand
flash驱动,
可以参考其他已经有的驱动,比如内核源码中已经有的
drivers/mtd/nand/s3c2410.c
就是个很好的例子。
自己以其为模板,实现自己板子的nand flash驱动。
其实主要工作就是,实现
static struct platform_driver s3c2410_nand_driver =
{
.probe =
s3c2410_nand_probe,
.remove =
s3c2410_nand_remove,
.suspend =
s3c24xx_nand_suspend,
.resume =
s3c24xx_nand_resume,
.driver = {
.name =
"s3c2410-nand",
.owner =
THIS_MODULE,
},
};
中的
XXX_nand_probe函数
XXX_nand_remove函数
XXX_nand_enable_hwecc,如果支持硬件ecc的话。
对nand flash的读写,这两个函数,实现了对nand的具体操作。
【Linux下Nand Flash驱动编写简单步骤】
软件和硬件知识,都已经了解的话,由于上层的linux的 mtd框架中,已经完全封装好了,对nand
flash的write page,write oob等相关函数的实现,那么剩下的只是相对来说已经是很少量的,关于nand
驱动具体内部操作方面的工作:
初始化
先是在nand 芯片初始化的时候,对其
XXX_nand_init_chip()
给对应的芯片chip赋给对应的
XXX_nand_read_buf和XXX_nand_write_buf等函数:
chip->cmd_ctrl =
XXX_nand_hwcontrol;
chip->dev_ready =
XXX_nand_devready;
chip->read_buf =
XXX_nand_read_buf;
chip->write_buf =
XXX_nand_write_buf;
以实现后续的对nand芯片的操作。
然后根据ecc类型,赋给对应的ecc的校验与纠错函数:
chip->ecc.hwctl =
XXX_nand_enable_hwecc;
chip->ecc.calculate = XXX
_nand_calculate_ecc;
3. 实现上面提到的对应的各个函数,关于如何实现,参考一下其他nand驱动,就会理解很多了。
4. 驱动测试,参考具体的 ldd3(Linux
Device Driver version 3)的测试相关部分内容。