title: NandFlash学习

tags: ARM

date: 2018-10-27 20:18:48:59

NandFlash学习

概述

  • NAND是公用数据线和地址线的,所以是需要命令操作的
  • NAND和其他内存接口公用数据线,所以需要片选信号
  • NAND有位反转,所以内部存在OOB(out of bank),这个一般无需cpu处理.,同时存在坏块,使用ecc处理

原理图(K9F2G08U0C)

启动的引脚配置

命令概述

操作概述

具体的操作时序,这个手册好评,短小好找

比如读操作

根据这个图就可以大致看出电平应该怎样,再查找时序图,基本就清楚了

地址信号操作,256M需要地址线=256*1024*1024*8=2^8*2^20=2^28也就是28个地址线

Uboot下操作体验

上述的操作,对于MCU来说就更简单了,读写相关寄存器即可.

NAND FLASH S3C2440
发命令 选中芯片->CLE设为高电平 输出命令值->在DATA0~DATA7上->发出一个写脉冲 NFCONT的bit1设为0,->NFCMMD=命令值
发地址 选中芯片->ALE设为高电平->在DATA0~DATA7上输出地址值->发出一个写脉冲 NFCONT的bit1设为0,->NFADDR=地址值
发数据 选中芯片->ALE,CLE设为低电平-> 在DATA0~DATA7上输出数据值->发出一个写脉冲 NFCONT的bit1设为0,->NFDATA=数据值
读数据 选中芯片->发出读脉冲->读DATA0~DATA7的数据 NFCONT的bit1设为0,->val=NFDATA

读ID

S3C2440 u-boot
选中 NFCONT的bit1设为0 md.l 0x4E000004 1; mw.l 0x4E000004 1
发出命令0x90 NFCMMD=0x90 mw.b 0x4E000008 0x90
发出地址0x00 NFADDR=0x00 mw.b 0x4E00000C 0x00
读数据得到0xEC val=NFDATA md.b 0x4E000010 1
读数据得到device code val=NFDATA md.b 0x4E000010 1
退出读ID的状态 NFCMMD=0xff mw.b 0x4E000008 0xff

Enter your selection: q
OpenJTAG> md.l 0x4E000004 1
4e000004: 00000003 ....
OpenJTAG> mw.l 0x4E000004 1
OpenJTAG> mw.b 0x4E000008 0x90
OpenJTAG> mw.b 0x4E00000C 0x00
OpenJTAG> md.b 0x4E000010 1
4e000010: ec .
OpenJTAG> md.b 0x4E000010 1
4e000010: da .
OpenJTAG> md.b 0x4E000010 1
4e000010: 10 .
OpenJTAG> md.b 0x4E000010 1
4e000010: 95
OpenJTAG> md.l 0x4E000010 1
4e000010: 44 D
OpenJTAG> mw.b 0x4E000008 0xff

读数据

uboot可以使用 nand dump 0 读取nand的内容

S3C2440 u-boot
选中 NFCONT的bit1设为0 md.l 0x4E000004 1; mw.l 0x4E000004 1
发出命令0x00 NFCMMD=0x00 mw.b 0x4E000008 0x00
发出地址0x00 NFADDR=0x00 mw.b 0x4E00000C 0x00
发出地址0x00 NFADDR=0x00 mw.b 0x4E00000C 0x00
发出地址0x00 NFADDR=0x00 mw.b 0x4E00000C 0x00
发出地址0x00 NFADDR=0x00 mw.b 0x4E00000C 0x00
发出地址0x00 NFADDR=0x00 mw.b 0x4E00000C 0x00
发出命令0x30 NFCMMD=0x30 mw.b 0x4E000008 0x30
读数据得到0x17 val=NFDATA md.b 0x4E000010 1
读数据得到0x00 val=NFDATA md.b 0x4E000010 1
读数据得到0x00 val=NFDATA md.b 0x4E000010 1
读数据得到0xea val=NFDATA md.b 0x4E000010 1
退出读状态 NFCMMD=0xff mw.b 0x4E000008 0xff
OpenJTAG> mw.b 0x4E000008 0xff
OpenJTAG> mw.l 0x4E000004 1
OpenJTAG> mw.b 0x4E000008 0x00
OpenJTAG> mw.b 0x4E00000C 0x00
OpenJTAG> mw.b 0x4E00000C 0x00
OpenJTAG> mw.b 0x4E00000C 0x00
OpenJTAG> mw.b 0x4E00000C 0x00
OpenJTAG> mw.b 0x4E00000C 0x00
OpenJTAG> mw.b 0x4E000008 0x30
OpenJTAG> md.b 0x4E000010 1
4e000010: 17 .
OpenJTAG> md.b 0x4E000010 1
4e000010: 00 .
OpenJTAG> md.b 0x4E000010 1
4e000010: 00 .

ID与地址编码

使用uboot读到的是EC-DA-10-95-44对比下第四字节的9515,也就是手册上写的是15=50ns/30ns,芯片读出来是95=25ns

  • Internal Chip Number =1
  • Number of

    Simultaneously

    Programmed Pages =2
  • Page Size=2kb
  • Block Size=128kb,所以1个block有128/2=64page
  • Redundant Area Size=16
  • Serial Access Minimum= 25ns
  • Plane Number=2
  • Plane Size=1Gb

最小擦除的单位是1个block=128k

内部的组织结构可以参考 K9F2G08UXA的数据手册

小结

发送地址addr的时候,先发col低地址也就是页内地址,再发高地址也就是第几个page.地址本身也还是先发送低位,也就是说col有2字节,先发低字节.

int page = addr / 2048;
int col = addr & (2048 - 1);//相当于addr%2048 /* 发出地址 */
/* col addr */
nand_addr_byte(col & 0xff);
nand_addr_byte((col>>8) & 0xff); /* row/page addr */
nand_addr_byte(page & 0xff);
nand_addr_byte((page>>8) & 0xff);
nand_addr_byte((page>>16) & 0xff);

时序初始化

NAND的时序参数实际上大体分为两种,发送命令、地址以及发送数据,下图是MCU的时序配置图

查看下NAND手册的命令时序图

  • 可以拿一个直尺来划分各时间点到拐角

  • 可以看出 CLE和ALE的时间参数是一致的

    • MCU中的TACLS 拐点在CLE有效之后TALS后才允许nWE有效,找到NAND中CLE>=12,tWp>=12.也就是说可以同时发出
    • TWRPH0为nWE的有效时间,对应NAND的tER>=12
    • TWRPH0为nWE失效到CLE失效的时间对应的是NAND的tCh>=5

其他寄存器设置如下

/*使能NAND FLASH控制器,初始化ECC,禁止片选*/
NFCONT = (1<<4) | (1<<1) | (1<<0);

程序设计

忙判断

手册上写: 软件模式下,你必须用定时查询或中断来检测 RnB 状态输入引脚。这个状态在NFSTAT的BIT0,0表示忙

void wait_ready(void)
{
while (!(NFSTAT & 1));
}

基本操作

void nand_deselect(void)
{
/*禁止片选*/
NFCONT |= (1<<1);
}
void nand_cmd(unsigned char cmd)
{
volatile int i;
NFCCMD = cmd;
for(i=0; i<10; i++);
}
void nand_addr_byte(unsigned char addr)
{
volatile int i;
NFADDR = addr;
for(i=0; i<10; i++);
}
unsigned char nand_data(void)
{
return NFDATA;
}
void nand_w_data(unsigned char val)
{
NFDATA = val;
}
void wait_ready(void)
{
while (!(NFSTAT & 1));
}

读NAND

void nand_read(unsigned int addr, unsigned char *buf, unsigned int len)
{
int i = 0;
int page = addr / 2048;
int col = addr & (2048 - 1); nand_select(); while (i < len)
{
/* 发出00h命令 */
nand_cmd(00); /* 发出地址 */
/* col addr */
nand_addr_byte(col & 0xff);
nand_addr_byte((col>>8) & 0xff); /* row/page addr */
nand_addr_byte(page & 0xff);
nand_addr_byte((page>>8) & 0xff);
nand_addr_byte((page>>16) & 0xff); /* 发出30h命令 */
nand_cmd(0x30); /* 等待就绪 */
wait_ready(); /* 读数据 */
for (; (col < 2048) && (i < len); col++)
{
buf[i++] = nand_data();
}
if (i == len)
break; col = 0;
page++;
} nand_deselect();
}

擦除

NAND的擦除单位是一个blok=64page=64*2k=128k

int nand_erase(unsigned int addr, unsigned int len)
{
int page = addr / 2048; if (addr & (0x1FFFF))
{
printf("nand_erase err, addr is not block align\n\r");
return -1;
} if (len & (0x1FFFF))
{
printf("nand_erase err, len is not block align\n\r");
return -1;
} nand_select(); while (1)
{
page = addr / 2048; nand_cmd(0x60); /* row/page addr */
nand_addr_byte(page & 0xff);
nand_addr_byte((page>>8) & 0xff);
nand_addr_byte((page>>16) & 0xff); nand_cmd(0xD0); wait_ready(); len -= (128*1024);
if (len == 0)
break;
addr += (128*1024);
} nand_deselect();
return 0;
}

写NAND

void nand_write(unsigned int addr, unsigned char *buf, unsigned int len)
{
int page = addr / 2048;
int col = addr & (2048 - 1);
int i = 0; nand_select(); while (1)
{
nand_cmd(0x80); /* 发出地址 */
/* col addr */
nand_addr_byte(col & 0xff);
nand_addr_byte((col>>8) & 0xff); /* row/page addr */
nand_addr_byte(page & 0xff);
nand_addr_byte((page>>8) & 0xff);
nand_addr_byte((page>>16) & 0xff); /* 发出数据 */
for (; (col < 2048) && (i < len); )
{
nand_w_data(buf[i++]);
}
nand_cmd(0x10);
wait_ready(); if (i == len)
break;
else
{
/* 开始下一个循环page */
col = 0;
page++;
} } nand_deselect();
}

其他注意

  • 使用nand 代码重定位的时候,注意make file 中的 链接文件 start ,nand 等文件放前面,保证在4k内

NandFlash学习的更多相关文章

  1. nandflash学习1——导致nandflash反转的原因【转】

    转自:http://blog.csdn.net/gaosentao/article/details/7711311 Bit Flip/Bit Flipping/Bit-Flip/Bit twiddli ...

  2. s3c6410学习笔记-将内核zImage、文件系统写到nandflash、屏幕校准

    1.之前已经将uboot写到nandflash里面了,接下来将内核zImage.文件系统写到nandflash. 2.编译内核 cd linux-2.6.28_smdk6410 make clean ...

  3. 驱动开发学习笔记. 0.02 基于EASYARM-IMX283 烧写uboot和linux系统

    驱动开发读书笔记. 0.02 基于EASYARM-IMX283 怎么烧写自己裁剪的linux内核?(非所有arm9通用) 手上有一块tq2440,但是不知道什么原因,没有办法烧boot进norflas ...

  4. 1.ok6410移植bootloader,移植u-boot,学习u-boot命令

    ok6410移植u-boot 既然是移植u-boot当然首先需要u-boot源码,这里的u-boot代码是由国嵌提供的. 一.配置编译u-boot A. 解压 u-boot 压缩文件 B. 进入解压生 ...

  5. ARM指令分类学习

    指令分类: 1.算数和逻辑指令 2.比较指令 3.跳转指令 4.移位指令 5.程序状态字访问指令 6.存储器访问指令 +++++++++++++++++++++++++++++++++++++++++ ...

  6. 嵌入式Llinux学习路线图

    版本 日期 作者 说明 V1 2016.07.29 韦东山 第1版本,Android部分未写 我是1999年上的大学,物理专业.在大一时,我们班里普遍弥漫着对未来的不安,不知道学习了物理后出去能做什么 ...

  7. NandFlash和iNand【转】

    转自:https://www.cnblogs.com/PengfeiSong/p/6380447.html nand 1.nand的单元组织:block与page(大页Nand与小页Nand)(1)N ...

  8. NandFlash和iNand

    nand 1.nand的单元组织:block与page(大页Nand与小页Nand)(1)Nand的页和以前讲过的块设备(尤其是硬盘)的扇区是类似的.扇区最早在磁盘中是512字节,后来也有些高级硬盘扇 ...

  9. EEPROM读写学习笔记与I2C总线(转)

    reference:https://www.cnblogs.com/uiojhi/p/7565232.html 无论任何电子产品都会涉及到数据的产生与数据的保存,这个数据可能并不是用来长久保存,只是在 ...

随机推荐

  1. JSON 解析 (三)—— FastJSON与Jackson比较

    一.方便性与性能 调用方便性而言: FastJSON提供了大量静态方法,调用简洁方便 Jackson须实例化类,调用相对繁琐,可通过封装成JSON工具类简化调用 性能而言: FastJSON反序列化的 ...

  2. HDU 4256 翻译罗马数字

    参考自:https://www.cnblogs.com/ECJTUACM-873284962/p/6414173.html The Famous Clock Time Limit: 2000/1000 ...

  3. Codeforces Round #530 (Div. 2) F (树形dp+线段树)

    F. Cookies 链接:http://codeforces.com/contest/1099/problem/F 题意: 给你一棵树,树上有n个节点,每个节点上有ai块饼干,在这个节点上的每块饼干 ...

  4. C#版本和.NET版本以及VS版本的对应关系

    C#版本和.NET版本以及VS版本的对应关系 版本 .NET Framework版本 Visual Studio版本 发布日期 特性 C# 1.0 .NET Framework 1.0 Visual ...

  5. How to intall and configure Haproxy on Centos

    Install Haproxy CentOS/RHEL 5 , 32 bit:# rpm -Uvh http://dl.fedoraproject.org/pub/epel/5/i386/epel-r ...

  6. 字符串数据结构模板/题单(后缀数组,后缀自动机,LCP,后缀平衡树,回文自动机)

    模板 后缀数组 #include<bits/stdc++.h> #define R register int using namespace std; const int N=1e6+9; ...

  7. 【拓扑排序】烦人的幻灯片(slides)

    1395:烦人的幻灯片(slides) 时间限制: 1000 ms         内存限制: 65536 KB提交数: 753     通过数: 416 [题目描述] 李教授将于今天下午作一次非常重 ...

  8. luogu3292 幸运数字 (点分治+线性基)

    首先第一眼是一个倍增套线性基,但是$O(Qlog^2Vlog^N)=10^{10}$的复杂度... 即使是st表也只是变成了$O(Nlog^2Vlog^N)$啊 考虑点分治,相对于倍增显著减少了线性基 ...

  9. [FJOI2016]神秘数(脑洞+可持久化)

    题目描述 一个可重复数字集合S的神秘数定义为最小的不能被S的子集的和表示的正整数.例如S={1,1,1,4,13}, 1 = 1 2 = 1+1 3 = 1+1+1 4 = 4 5 = 4+1 6 = ...

  10. centos7安装sonarqube6.7 代码质量管理平台

    应用介绍:SonarQube是一个用于代码质量管理的开源平台,用于管理源代码的质量通过插件形式:    可以支持包括java,C#,C/C++,PL/SQL,Cobol,JavaScrip,Groov ...