关于块设备与nand flash的初步小结

本文介绍了块设备驱动的框架,从应用程序读写到硬件的调用过程,重点讲解了块设备驱动中的gendisk结构体和相关注册、反注册函数。同时,详细讨论了NAND Flash的硬件特性,包括其接口信号、时序参数配置,以及S3C2440中对NAND Flash的操作寄存器。此外,还提到了NAND Flash驱动的基本结构体及初始化过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

块设备驱动的框架:

调用过程自上而下为:应用程序读写文件—>虚拟文件系统(ext3, yaffs2, jffs2)—>由ll_rw_block函数转换成扇区的读写—>块设备驱动程序—>读写硬件

块设备驱动程序提供一个队列,将读操作和写操作放入队列内,并且在队列中优化读写顺序使得读写占用时间减小(这就是为什么有时候读的数据可能并不是真正从磁盘上读来的而是cache中),设备驱动另外必要的功能就是要注册设备。原理上字符设备也同样可以对字盘读写,只是少了块设备驱动那样的电梯调度算法。

块设备驱动中重要的数据结构:

struct gendisk:可使用函数alloc_disk分配;

一个简单的块设备驱动需要给以下结构体内的值进行赋值:

struct gendisk {
/* major, first_minor and minors are input parameters only,
* don't use directly.  Use disk_devt() and disk_max_parts().
*/

…………

struct request_queue *queue;//使用blk_init_queue函数设置队列,队列中包括读写的操作

int major; /* major number of driver *///使用register_blkdev注册到一个主设备号

int first_minor;

int minors;                     /* maximum number of minors, =1 for
                                         * disks that can't be partitioned. */

char disk_name[DISK_NAME_LEN];/* name of major driver */

struct block_device_operations *fops;
struct hd_struct part0;//使用set_capacity函数设置有多少个扇区

…………
};

最后注册gendisk,使用函数:add_disk函数。

对以上相关的结构体进行反注册的函数有:unregister_blkdev(major, "blockdisk");del_gendisk(block_disk);put_disk(block_disk);blk_cleanup_queue(block_queue);

关于调试块设备的相关命令:

mkdosfs:第一次使用一块块设备需要对其进行格式化;fdisk对一个块设备进行分区。

nand flash的驱动相关:

nand flash硬件:

如果所示:


其中:

I/O0 ~ I/O7:用于输入地址/数据/命令,输出数据;

WP#:Write Protect,写保护;

WE#:Write Enable,写使能, 在写取数据之前,要先使WE#有效;

ALE:Address Latch Enable,地址锁存使能,在输入地址之前,要先在模式寄存器中,设置ALE使能;

CLE:Command Latch Enable,命令锁存使能,在输入命令之前,要先在模式寄存器中,设置CLE使能;PS:当ALE和CLE都不使能的时候表示当前传输的是数据;

CE#:Chip Enable,片选使能,在操作Nand Flash之前,要先选中此芯片,才能操作;

RE#:Read Enable,读使能,在读取数据之前,要先使CE#有效;

R/B#:Ready/Busy Output,就绪/忙,主要用于在发送完编程/擦除命令后,检测这些操作是否完成,忙,表示编程/擦除操作仍在进行中,就绪表示操作完成;

S3C2440中NFCONF中三个比较重要的参数:

TACLS、TWRPH0、TWRPH1:S3C的数据手册如下:


如上图可猜测

TACLS为CLE/ALE使能至nFRE/nFWE使能之间的时间段;TACLS设值范围0-3,持续时间的公式为TACLS*HCLK

TWRPH0为nFRE/nFWE使能的时间段;TWRPH0设值范围0-7,持续时间的公式为(TWRPH0+1)*HCLK

TWRPH1为nFRE/nFWE不使能至CLE/ALE不使能的时间段;TWRPH1设值范围0-7,持续时间的公式为(TWRPH1+1)*HCLK

查阅NAND FLASH的数据手册:


观察时序图以及下图可以发现:

TACLS:对应于nand flash手册中时序图(tCLS-tWP)和(tALS-tWP)这两个值中的较小的那个。12ns-12ns=0。所以TACLS可设置为0。

TWRPH0:对应于nand flash手册中时序图tWP和tRP这两个值中的较小的那个。(tRP也是12ns,未截图)。12ns。假设HCLK为100Mhz,根据公式(TWRPH0+1)*HCLK=12ns,可算得TWRPH0=1.2=2。

TWRPH1:对应于nand flash手册中时序图tCLH和tALH这两个值中的较小的那个。同上。

关于S3C中对NAND FLASH操作的寄存器:

nfconf  ;0x4E000000
nfcont  ;
nfcmd   ;
nfaddr  ;
nfdata  ;
nfeccd0 ;
nfeccd1 ;
nfeccd  ;
nfstat  ;
nfestat0;
nfestat1;
nfmecc0 ;
nfmecc1 ;
nfsecc  ;
nfsblk  ;
nfeblk  ;

关于NAND FLASH驱动的基本框架:

基本的结构体:

struct nand_chip、struct mtd_info、struct mtd_partition

nand_chip结构体中需要满足的结构体成员:

select_chip   //为片选NAND FLASH的操作函数
cmd_ctrl //为发送命令或者地址的操作函数(把数据放入CMD寄存器还是ADD寄存器)
IO_ADDR_R //为读数据的寄存器
IO_ADDR_W//为写数据的寄存器
dev_ready //为检测nand flash是否忙的函数
ecc.mode //为是否ECC校验的标志位如NAND_ECC_SOFT或者NAND_ECC_NONE等

mtd_info结构体中需要满足的结构体成员:

owner //THIS_MODULE;
priv  = s3c_nand;//指向nand_chip的结构体,用于nand_scan识别nand flash用。

识别之后注册分区add_mtd_partitions函数。(反注册函数del_mtd_partitions)。

PS:过程中需要使能NAND FLASH控制器的时钟,使用函数clk_get、clk_enable。

以上完成了nand flash块设备的初始化,其中调用的函数中肯定调用了一开始说的那些函数,底层设备的初始化都会一步步调用到上层的函数,因为初始化完成之后就可以用应用程序对其访问。

NOR FLASH:


上图可得其数据位有16位,地址位有22位除去两位NC为22位,2^20=1024*1024,由数据位为16位可得,总共容量有2Mb(这样我们也大概清楚为什么nand不用这样的总线寻址了,因为容量太大线太多了)。

关于为什么是LADDR1接A0而不是LADDR0接,是因为S3C2440每个地址的容量为一个字节而非此NOR中两个字节,为了让这样一倍的差距对应起来,如果ARM程序中总线的地址为0x2而对应NOR中的地址就是0x1,如果总线地址为0x3那么NOR中还是0x1,因为0x2、0x3两个地址的值都位于地址为0x1的16位寄存值中。

nor编程系统框架:

结构体:map_info、s3c_nor_parts

函数:

simple_map_init、do_map_probe、add_mtd_partitions


参考文章:

http://blog.youkuaiyun.com/juana1/article/details/6577556

http://funexploit.readthedocs.org/en/latest/sources/embeddedsystem.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值