硬件原理:
NAND FLASH是一个存储芯片
- 引脚图
- 主芯片连接引脚
- NAND FLASH引脚:
- 引脚说明:
- 需求分析思考:
那么:这样的操作很合理“都地址A的数据,把数据B写道地址A” 问1.原理图上NAND FLASH和S3C2440之间只有数据线, 怎么传输地址? 答1.在DATA0~DATA7上及传输数据,又传输地址 当ALE为高电平时传输地址 涉及引脚:DATA0~DATA7 问2.NAND FLASH芯片手册可知,要操作NAND FLASH需要先发出命令 如何发出命令 答2.在DATA0~DATA7上及传输数据,又传输地址,也传输命令 当ALE为高电平时传输的是地址, 当CLE为高电平时传输的是命令, 当ALE和CLE均为高电平时传输的是数据, 涉及引脚:ALE + CLE 问3.数据线既接到NAND FLASH,也街道NOR FLASH,还接到SDRAM,DM9000等 那么如何避免干扰 答3.这些设备,要访问之前必须“选中”,低电平有效 没有选中的芯片不会工作,相当于没有接一样 涉及引脚::nFCE 问4.假设烧写NAND FLASH,把命令、地址、数据发给它之后, NAND FLASH不可能瞬间完成烧写, 如何判断烧写完成? 答4.通过状态引脚RnB来判断:高电平表示就绪 / 低点评表示正忙 涉及引脚:RnB 问5.怎么操作NAND FLASH呢? 答5.根据NAND FLASH的芯片手册,一般的过程是: 发出命令 发出地址 发出数据/读数据 NAND FLASH S3C2440 发命令 选中芯片 CLE设置为高电平 在DATA0~DATA7上输出命令值 NFCMD = 命令值 发出一个写脉冲 发地址 选中芯片 ALE设置为高电平 在DATA0~DATA7上输出地址值 NFADDR = 命令值 发出一个写脉冲 发数据 选中芯片 CLE + ALE 设置为高电平 在DATA0~DATA7上输出数据值 NFDATA = 数据 发出一个写脉冲 读数据 选中芯片 //CLE + ALE 设置为高电平 读DATA0~DATA7的数据 val = NFDATA
- 命令操作集:
-
NAND FLASH驱动具体要实现的封装功能无非读/写/擦除,依据如下操作集进行相关元接口封装,共FLASH驱动框架调用即可
-
举例
-
Read ID Operation
使用uboot来体验NAND FLASH的操作 S3C2410 UBOOT 选中 NFCONT的bit1设置为0 md.l 0x4E000004 1;mw.l 0x4E000004 1 发出命令0x90 NFCMD=0x90 mw.l 0x4E000008 0x90 发出地址0x00 NFADDR=0x00 mw.l 0x4E00000C 0x00 读取数据得到0xEC val=NFDATA md.l 0x4E000010 1 读取数据得到Device Code val=NFDATA md.l 0x4E000010 1 退出读取ID的状态 NFCMD=0xff mw.l 0x4E000008 0xff
-
读内容:读0地址的数据
使用uboot命令: nand dump 0 Page 00000000 dump: 17 00 00 ea 14 f0 S3C2410 UBOOT 选中 NFCONT的bit1设置为0 md.l 0x4E000004 1;mw.l 0x4E000004 1 发出命令0x00 NFCMD=0x00 mw.l 0x4E000008 0x00 //00h 发出地址0x00 NFADDR=0x00 mw.l 0x4E00000C 0x00 //Col.Add1 发出地址0x00 NFADDR=0x00 mw.l 0x4E00000C 0x00 //Col.Add2 发出地址0x00 NFADDR=0x00 mw.l 0x4E00000C 0x00 //Row.Add1 发出地址0x00 NFADDR=0x00 mw.l 0x4E00000C 0x00 //Row.Add2 发出命令0x30 NFCMD=0x00 mw.l 0x4E000008 0x00 //30h 读取数据得到0x17 val=NFDATA md.l 0x4E000010 1 读取数据得到0x00 val=NFDATA md.l 0x4E000010 1 读取数据得到0x00 val=NFDATA md.l 0x4E000010 1 读取数据得到0xea val=NFDATA md.l 0x4E000010 1 退出读状态 NFCMD=0xff mw.l 0x4E000008 0xff
-
-
驱动框架
APP open,read,write,ioctl
vfs----sys_open,sys_read,sys_write
FS vfat,ext2,ext3,yaff2
字符设备 块设备 知道怎么优化
块设备驱动:ll_rw_block 怎么写块设备驱动程序
把“读写”放入队列 1.分配gendisk---alloc_disk
NAND FLASH协议: 知道怎么发,来读写、擦除
硬件相关: 知道发什么,命令地址,读写数据
1.分配
2.设置
3.硬件相关操作
优化后执行 2.设置
a.队列:blk_init_queue
b.其他属性
3.注册---add_disk
内核启动打印:
驱动程序
s3c24xx_nand_probe
s3c2410_nand_inithw
s3c2410_nand_setrate------设置时钟周期(tacls,twrph0,twrph1)
writel(S3C2440_NFCONT_ENABLE, info->regs + S3C2440_NFCONT);------使能nand flash
#define S3C2440_NFCONT_ENABLE (1<<0)
MODE [0] NAND Flash 控制器运行模式
0:NAND Flash 控制器禁止(不工作) 1:NAND Flash 控制器使能
s3c2410_nand_init_chip--------注册芯片独立的读写,命令,状态读取相关接口
nand_scan_ident
nand_get_flash_type 解析函数nand_get_flash_type
/* Select the device */
chip->select_chip(mtd, 0); ----选中
/* Reset the chip */
//chip->cmdfunc = nand_command
chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); ----复位(退出上次状态) 发送0xff
/* Send the command for reading device ID */
//NAND_CMD_RESET = 0xff
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); ----读取Device ID 发送命令0x90
发送地址0x00
//NAND_CMD_READID = 0x90
/* Read manufacturer and device IDs */
*maf_id = chip->read_byte(mtd); ----读取厂商ID
*dev_id = chip->read_byte(mtd); ----读取设备ID
/* Read entire ID string */
for (i = 0; i < 8; i++)
id_data[i] = chip->read_byte(mtd); ----读取前8字节,开始解析flash各硬件参数
nand_scan_tail
s3c2410_nand_add_partition
mtd_device_register
add_mtd_device
list_for_each_entry(not, &mtd_notifiers, list)
not->add(mtd);
s3c2410_nand_cpufreq_register