加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ARM第六天(Nand Flash 上)

发布时间:2020-12-15 19:58:35 所属栏目:百科 来源:网络整理
导读:1,什么是Nand fash? 存储设备,用于存储整个系统(引导程序、内核、文件系统),相当于PC中的硬盘。 2,TPAD采用了什么Nand Flash 三星公司的K9K8G08U0B型号的Nand Flash。 3,如何才能操作Nand Flash,主要是对它进行写操作,读操作,校验操作 需要阅读Nan

这里写图片描述


1,什么是Nand fash?
存储设备,用于存储整个系统(引导程序、内核、文件系统),相当于PC中的硬盘。

2,TPAD采用了什么Nand Flash
三星公司的K9K8G08U0B型号的Nand Flash。

3,如何才能操作Nand Flash,主要是对它进行写操作,读操作,校验操作
需要阅读Nand flash的datasheet,该手册会详细描述如何操作nand falsh的正确方法。

4,Nand Flash能用特性
1),Nand Flash在没写数据之前,Nand Flash都是1
2),如果已经写了数据 ,再写数据,必须先擦除
在Nand Flash只有将1改成0的能力,没有将0改成1的能力。
3),Nand Flash在出厂时,可能存在坏块,但是不影响使用,并且保证第一块一定是好块。
4),Nand Flash的擦写次数有限。100K 次

5,K9K8G08U0B Nand Flash的主要指标参数
1),工作电压: 3.3V
2),容量:(1G + 32M) x 8bit
3),写操作:按页(2K+66)Byte
擦除操作:按块(128K+4k)Byte
4),页大小:(2K+64)Byte
块大小: (128+4K)Byte
1块 = 64页
5),IO管脚复用:命令、地址、数据复用IO口
6),Nand Flash可以100K次的写、擦除
数据保存时间:10年
7),通过命令来操作Nand flash
8),Nand flash存在唯一的ID号
9),Nand flash封装形式

这里写图片描述

Nand Flash共有48个管脚,并不是每个管脚都使用了。
N.C:没有使用,无连接的管脚,可以不用管
Vcc:电源
Vss:接地
nCE:低电平有效,片选信号,低电平有效
IO0-IO7:8个IO管脚,功能复用,传输命令、地址,数据
CLE:高电平有效,命令锁存信号,如果这个信号为高,表示IO0-IO7传输的是命令
ALE:高电平有效,地址锁存信号,IO0-IO7传输的是地址。CLE、ALE不同时为高
当CLE、ALE都为低电平时,IO0-IO7传输的是数据
CLE ALE
1 0 命令
0 1 地址
0 0 数据
nWE:低电平有效,写使能. 可以写命令、写地址、写数据
nRE:低电平有效,读使能
nWP:低电平有效,写保护
R/nB:当前Nand flash的状态
R:高电平,表示Ready,准备就绪
nB:低电平,表示Busy,忙

Nand Flash芯片上的各个管脚实际上与S5PV210处理器中的Nand Falsh控制器相连(所谓Nand flash控制器从表现形式上看,也就是一引起S5PV210上管脚,只是部分管理的主要功能是用来控制Nand Flash),因此,我们不用直接去操作Nand flash的管脚,而是通过操作Nand Flash控制器中的寄存器来实现对Nand Flash的操作。

Nand Flash控制器的寄存器的地址范围:

这里写图片描述


SFRS特殊功能寄存器

Nand Flash的内部结构图:

这里写图片描述


1,页:构成Nand Flashr的基本单位,页大小固定
1 page = (2K + 64)bytes = (2048(main) + 64(spare))bytes
每一页又分为main区和spare区
main区:用于正常数据的存储
spare区:用于存储一些附加信息,如坏块的标志,块的逻辑地址,ECC校验信息
2,块:由若干页构成,64页构成一块,块大小固定
1 block = (2K+64)bytes * 64 page = (128K(main)+4K(spare))bytes
3,device:由若干块构成,8192块
1 device = (128K + 4K)*8192 = (1G + 32M)bytes = (1024M+32M)bytes=(1056M)bytes = 8448Mbits

Nand Flash:(1G+32M)bytes
1G字节:存储主数据,main区
32M字节:存储附加信息,spare区

块号:8192块,0~8191块
页号:8192*64 = 524288页 ,0~524287页

表示Nand Flash地址,需要多少bit来表示一个字节的地址?

这里写图片描述

31bit地址如何发送?
IO0-IO7 8个IO管脚,一次只能发8bit
由于Nand Flash是I/O接口,复用,只用用8根IO线发送地址一次发8bit,共分5个周期(Nand Flash的datasheet定义)
5个周期:
1周期:A0-A7(页内地址,列地址)
2周期:A8-A11 0000 (页内地址,列地址)
3周期:A12-A19(页内地址,行地址)
4周期:A20-A27 (页内地址,行地址)
5周期:A28-A30 0000

案例:
列地址(页内地址):2048
行地址(行号):518400

如何发送?
2048 00001000,00000000
518400 00000111,11101001,00000000

由Nand Flash的Datasheet可知,Nand Flash是通过命令来操作的:

这里写图片描述

Nand Flash不一样,对应的命令集不一样。

Nand Flash:
通用特性:
具体特性:

Nand Flash管脚:
Nand Flash内部结构 :页、块
地址:31bit,分5个周期来发送
命令集:

Nand Flash 控制器:
阅读S5PV210 datasheet P692
1,支持Nand Flash页大小:512Bytes,2KB,4KB,8KB
2,可以通过软件编程的方式实现对Nand Flash进行读操作、写操作、擦除操作
3,支持8bit的IO口的Nand Flash.
4,硬件可以产生,监测ECC校验码,软件纠正。
5,支持SLC和MCL两种工艺的Nand Flash
6,ECC:支持1481216 bit ECC
7,特殊功能寄存器的访问方式。
Data(数据寄存器NFDATA)和ECC data数据寄存器,可以采用字节,半字,字的方式访问,其余寄存器采用字方式访问。

这里写图片描述

寄存器

这里写图片描述

如何通过软件编程的方式操作Nand Flash(P695)
1,向命令寄存器(NFCMMD)写入操作Nand Flash的命令
2,向地址寄存器(NFADDR)写入要操作Nand Flash的具体地址
3,向数据寄存器(NFADATA)写入要向Nand Flash写主的数据
4,从数据寄存器(NFADATA)读出Nand Flash的数据
5,读出main区和spare区的ECC校验信息,进行数据校验

NFCONF 配置寄存器

这里写图片描述


这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

HCLK = 133MHZ = 7 ns;

TACLS:表征的是从CLE(命令锁存信号)/ALE (地址锁存信号)有效,到nWE写使能信号有效经过的时间Druation1.
Druation1 = HCLK * TACLS = 7ns * TACLS >=0
= tCLS - tWP = tALS - tWP
= 12 - 12 = 12 - 12
TACLS = 15
TWRPH0:表征的是nWE写使能信号的有效时间Druation2。
Druation2 = HCLK *(TWRH0+1)
= 7ns *(TWRH0+1)>=12
= tWP
= 12 ns
TWRH0 = 15
TWRPH1:表征的是nWE写使能信号无效之后,CLEALE信号还要维持的时间Druation3。
Druation3 = HCLK *(TWRPH1+1)
= 7ns *(TWRPH1+1)>=5
= tCLH = tALH
= 12 ns
TWRPH1 = 15

NFCONT 控制寄存器

这里写图片描述


NFCMMD命令寄存器

这里写图片描述


NFADDR地址寄存器

这里写图片描述


NFDATA数据寄存器

这里写图片描述


这里写图片描述

NFSTAT状态寄存器

读时序图:

这里写图片描述

read Nand Flash 的ID案例
nand.h

#define __NAND_H__
#define __NAND_H__

//定义寄存器
#define NFCONF (*((volatile unsigned int*)0xBOE00000));
#define NFCONT (*((volatile unsigned int*)0xBOE00004));
#define NFCMMD (*((volatile unsigned int*)0xBOE00008));
#define NFADDR (*((volatile unsigned int*)0xBOE0000C));
#define NFDATA (*((volatile unsigned int*)0xBOE00010));
#define NFSTAT (*((volatile unsigned int*)0xBOE00028));

//声明函数原型
extern void nand_init(void);
extern void nand_read_id(void);

#endif

nand.c文件:

#include "nand.h"
#include "uart.h"
#include "itoa.h"

void nand_init(void)
{
   //nand flash 控制器使用的管脚配置,
   //因为我们使用的nand flash启动方式,所以关于GPIO管脚功能配置可以不做
   //如果使用的不是nand flash启动,将需要配置
   NFCONF = (0xF<<12) | (0xF<<8) |(0xF<<4) | (1<<1); 
   NFCONT = (3<<12) | (3<<8) | 7; 
}

void nand_read_id(void)
{
   //1,nand falsh片选信号拉低,使能nand falsh芯片
   //操作 NFCONT bit[1] = 0;
   NFCONT &= ~(1<<1);// 1<<1 ==> 10
   //2,向NFCMMD寄存器写入0x90
   NFCMMD = 0x90;
   //3,向NFADDR寄存器写入0x0
   NFADDR = 0x0;
   //4,延时
   int i;
   for(i = 0;i < 256; i++)
   {
      ;
   }
   //5,读NFDATA 寄存器(字)ID
   //读5个字节的ID号
   unsigned int id1;
   unsigned int id2;
   id1 = NFDATA;
   id2 = (NFDATA & 0xFF);//只要低八位
   //6,Nand flash片选信号拉高
    //操作 NFCONT bit[1] = 1;
   NFCONT |= (1<<1) ;
   //7,显示读出来的nand flash的ID号
   char buf[16];
   uart0_puts("n ID1 = ");
   itoa(buf,id1);//转换(整型无法直接打印,打印前转换成字符串)
   uart0_puts(buf);//输出

   uart0_puts("n ID2 = ");
   itoa(buf2,id2);//转换
   uart0_puts(buf2);//输出
}

说明:
NFCONF = (0xF<<12) | (0xF<<8) |(0xF<<4) | (1<<1),
1<<1 ? 10
0xF<<4 ==>1111,0000
0xF<<8 ==>1111,0000,0000
0xF<<12==>1111,0000
(0xF<<12) | (0xF<<8) |(0xF<<4) | (1<<1) = 1111,1111,0010

cmd.c

#include "cmd.h"
#include "led.h"
#include "nand.h"

void cmd_ledon(void)
{
    //调用开灯函数
    led_on();
}

void cmd_nid(void)
{
    //调用读nand flash Id函数
    nand_read_id();
}

void cmd_ledoff(void)
{
    //调用关灯函数
    led_off();
}
const cmd_t cmd_tb1[] =
{
    {"ledon",cmd_ledon},{"ledoff",cmd_ledoff},{"nid",cmd_nid},};

int cmd_tab1_num = sizeof(cmd_tb1)/sizeof(cmd_tb1[0]);

cmd_t *find_cmd(const char *name)
{
    for(int i=0;i<cmd_tab1_num;i++)
    {
      if(name == cmd_tb1[i].name)
      {
         return cmd_tb1[i];
      }  
    }
    return NULL;
}

main.c

#include "uart.h"
#include "strcmp.h"
#include "led.h"
#include "nand.h"

#define int BUF_LEN = 10;
#define char buf[BUF_LEN];
void main(void)
{
    char ch;
    //1,初始化串口
    uart0_init();
    led_init();
    nand_init();

    //2,发送一个字符串
    while(1){
        uart0_puts("n Shell#");
    }
}

makefile 略

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读