nand flash控制
结构
引脚名称 | 引脚功能 |
---|---|
I/$O_0$ - I/$O_7$ | 数据输入输出 |
CLE | 命令锁存使能 |
ALE | 地址锁存使能 |
$\overset{-}{CE}$ | 芯片使能 |
$\overset{-}{RE}$ | 读使能 |
$\overset{-}{WE}$ | 写使能 |
$\overset{-}{WP}$ | 写保护 |
$R/\bar{B}$ | 就绪/忙输出信号 |
$V_{cc}$ | 电源 |
$V_{ss}$ | 池 |
NC | 不接 |
K9F1208U0M容量64mb,每一页的大小是512字节,并且每一页上还有额外的字节。也就是说总共有$2^{18}$个字节
读写nand的过程:
- 发出命令字
- 发出地址
- 读写数据
命令字及操作方法
命令 | 第一个周期 | 第二个周期 | 第三个周期 |
---|---|---|---|
Read1(读) | 00h/01h | - | - |
Read2(读) | 50h | - | - |
Read ID(读芯片ID) | 90h | - | - |
Page Program(写页) | 80h | 10h | - |
Block Erase(擦除块) | 60h | D0h | - |
Read Status(读状态) | 70h | - | - |
Read Multi-Plane Status (读多层状态) |
71h | - | - |
Reset(复位) | FF | - | - |
Page Program (Dummy) | 80h | 11 | - |
Copy-Back Program(True) | 00 | 8a | 10 |
Copy-Back Program(Dummy) | 03 | 8a | 11 |
Multi-Plane Block Erase | 60 | D0 | - |
命令字后发送的地址序列
I/O 0 | I/O 1 | I/O 2 | I/O 3 | I/O 4 | I/O 5 | I/O 6 | I/O 7 | 备注 | |
---|---|---|---|---|---|---|---|---|---|
第一个地址序列 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 列地址 |
第二个地址序列 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 行地址(页地址) |
第三个地址序列 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 行地址 |
第四个地址序列 | 25 | - | - | - | - | - | - | - | 行地址 |
列地址是为了选择行内具体某个位置的,可以看到列地址可以选择256个字节,因此读命令00表示前256个字节,而01表示后256个字节。总共发出的地址数也只有25个,还有一位就是由命令决定的。
每一页共有528个字节,分为三部分,前256个称为A区,中间256个称为B区,最后16个字节称为C区。A区命令字为00h,B区01h,C区50h。
- Read1: 00或01。决定读A区还是B区,然后发送地址开始读数据
- Read2: 50h。读C区
- Reset: FF。复位NAND FLASH芯片,如果正在处于读、写、擦除撞他那么会终止这些命令。
- Page Program(True): 写数据。分为两阶段,80和10
NAND写操作一般都是以页为单位的,但是可以只写一部分,首先发送80后发送4个地址序列,然后向Flash中发送数据,然后发出命令字10h启动写操作,此时Flash内部会自动完成写、校验操作。一旦发出命令字10后,就可以使用70获知当前写操作是否完成 - Page Program(Dummy):命令字为80和11
如图所示每个为512m的flash存储器,有四个128m存储器(Plane)排列构成。因此我们可以在4个连续的块内同时进行写或者擦除操作 Copy-Back Program(True): 该命令将一页复制到同一个Plane中的另一页,它省略了独处再写入的过程,加快了速度。它的命令字分为三个阶段,00h,8ah, 10h
首先发送读命令,然后发送地址,将这528个字节存到内部存储器中,然后发出8ah, 再发出目标地址序列,最后发10h启动写操作
Block Erase: 擦除NAND Flash块。命令分为三个阶段
一块的大小为16Kb,有32页,在发出命令字60后,发出block地址,只需要发出三个行地址,并且A9-A13被忽略。然后发出Do和70
- 读状态命令有两种70和71,在Flash中有状态寄存器,启动读操作可以读入此寄存器,状态寄存器的含义如下表所示
I/O引脚 | 所标志的状态 | 70对应含义 | 71对应含义 |
---|---|---|---|
I/O0 | 总标记,成功或失败 | 成功0,失败1 | 同70 |
1 | Plane0标记 | 忽略 | 成功0,失败1 |
2 | Plane1标记 | … | … |
3 | Plane2标记 | … | … |
4 | Plane3标记 | … | … |
5 | 保留 | 忽略 | 忽略 |
6 | 设备状态 | 忙: 0 , 就绪:1 | 成功0,失败1 |
7 | 写保护状态 | 保护0, 没有保护1 | 同70 |
寄存器介绍
NAND FLash的读写顺序如下:
- 设置NFCONF寄存器
- 向NFCMD寄存器写入命令
- 向NFADDR写入地址
- 读写数据,通过NFSTAT检测NAND Flash状态,在启动某个操作后,应检测R/nB信号判断该操作是否已经完成
寄存器介绍
- NFCONF: 在S3C2440中用来设置时序参数TACLS、TWRPH0、TWRPH1,设置数据位宽,还有一些只读位,用来指示是否支持其他大小的页
- NFCONT:用来使能/禁止NAND Flash,使能/禁止控制引脚信号nFCE、初始化ECC
- NFCMD: 写入命令字
- NFADDR: 写这个寄存器就会按序发出地址信号
- NFDATA: 只用到低8位,读写此寄存器将启动对NAND Flash的读写操作
- NFSTAT: 只用到最低位,0: busy, 1: ready
实例
示例的存储器容量为128M并且一页大小为2048
片选是由于存储器往往有很多个芯片,而片选是选择这些芯片中的某一个。例如s3c2440中将1G的地址分为8段,有3位地址线译码进行控制,片选信号决定选择哪个地址段。head.s
0x48000000 MEM_CTL_BASE,
0x30000000 SDRAM_BASE,
0x30004000 PROGRAM_BASE,
@ 从NAND启动 时, 会通过内部硬件将NAND FLASH开始的4kb数据复制到
@ 称为Steppingstone的4kb内部RAM中(起始地址为0), 然后跳转到0开始执行
@ bl是相对跳转指令,并且返回值存在R14中, ldr是搬运数据指令,如果有=号表示将某个值给某个寄存器(伪指令),否则用该地址的数据进行跳转
_start
_start:
ldr sp, =4096
bl disable_watch_dog @ 关闭WATCHDOG,否则 会不断重启
bl memsetup @ 设置存储控制器
bl nand_init
ldr r0, =0x30000000 @1. 目标地址=0x30000000,这是SDRAM的起始地址
mov r1, #8192 @2. 源地址 = 4096,连接的时候,main.c中的代码都存在NAND Flash地址4096开始处
mov r2, #2048 @3 复制长度= 2048(bytes),对于本实验的main.c,这是足够了
bl nand_read @调用C函数nand_read
ldr sp, =0x34000000 @设置栈
ldr lr, =halt_loop @设置返回地址
ldr pc, =main @b指令和bl指令只能前后跳转32M的范围,所以这里使用向pc赋值的方法进行跳转
on_sdram:
ldr sp, =0x34000000 @ 设置栈
bl main
halt_loop:
b halt_loop
disable_watch_dog:
mov r1, #0x53000000 @ 看门狗是一个硬件,一段时间没有写值会自动重启,关闭需要在该位置置零
mov r2, #0x0
str r2, [r1]
mov pc, lr @ 返回, lr的值给pc
memsetup:
@ 设置存储控制器以便使用sdram等外设
mov r1, #MEM_CTL_BASE @ 存储控制器的13个寄存器开始地址
adrl r2, mem_cfg_val @ 13个值的初始存储地址
add r3, r1, #52 @ 13 * 4 = 52
1:
ldr r4, [r2], #4 @ 读取设置值,并让r2加4
str r4, [r1], #4
cmp r1, r3
bne 1b
mov pc, lr
4
mem_cfg_val:
@ 存储控制器13个寄存器的设置值
0x22011110 @ BWSCON, 每r位控制一个bank, 0位为启用SDRAM的数据掩码,如果为0则启用SDRAM,为1启用SRAM, 1位是否启用wait信号,通常为0,后面两位设置位宽,00 是8位,01是16位,10是32位
0x00000700 @ BANKCON0 0-5是时序控制,默认的700就足以
0x00000700 @ BANKCON1
0x00000700 @ BANKCON2
0x00000700 @ BANKCON3
0x00000700 @ BANKCON4
0x00000700 @ BANKCON5
@ 6-7可以接sdram或sram, 因此有所不同.[16: 15]表示是sdram(11)还是sram(00,且设置和0-5相同),如果是sdram,则[3: 2]ras to cas delay,推荐01。[1: 0]列地址位数00是8位,01是9位,10是10位
0x00018005 @ BANKCON6
0x00018005 @ BANKCON7
0x008c07a3 @ REFRESH [23]: 是否启用刷新,1启动。[22]:刷新模式.[21: 20]设置成0, [19:18]:默认11,[10: 0]: 是R_CNT=2^11 + 1 - SDRAM时钟频率*SDRAM刷新周期
0x000000b1 @ BANKSIZE [7]:如果为1核支持突发传输 [5]:1为使用scke信号进入省电模式 [4]: 1仅在访问SDRAM期间发出SCLK(推荐)[2: 0]: 设置bank6-7大小
0x00000030 @ MRSRB6, 设置sdram时序
0x00000030 @ MRSRB7
nand_init.c |
main.c |