(嵌入式Linux 9 )NAND

NAND操作原理

硬件连接

NAND与2440电路连接图

1.NAND FLASH和S3C2440之间只有数据线,在DATA0~DATA7上既传输数据,又传输地址,当ALE为高电平时传输的是地址。

2.在DATA0~DATA7上既传输数据,又传输地址,也传输命令
   当ALE为高电平时传输的是地址,
   当CLE为高电平时传输的是命令
   当ALE和CLE都为低电平时传输的是数据

3.通过状态引脚RnB来判断:它为高电平表示就绪(烧写完成),它为低电平表示正忙

4.操作步骤: 发出命令,发出地址,发出数据/读数据

NAND 控制器

2440内部有NAND 控制器。在 NAND Flash 中执行引导代码,在 SDRAM 中执行主代码。可以通过寄存器控制,向NANDflash发送指令或读取数据。其中包括NFCMMD命令寄存器,NFADDR地址寄存器,NFDATA数据寄存器。读取数据时可以从NFDATA中读取。

所以,对于NANDFLASH的操作,可以总结为:CPU只需操作nandflash控制器的寄存器,nandflash控制器会自动与NANDFLASH进行数据通信。

                         2440--> NAND FLASH                                        CPU--> S3C2440
发命令                     选中芯片                   
                              CLE设为高电平                                              NFCMMD=命令值     
                      在DATA0~DATA7上输出命令值
                              发出一个写脉冲
            
发地址                       选中芯片                                                      NFADDR=地址值
                            ALE设为高电平
                       在DATA0~DATA7上输出地址值
                                发出一个写脉冲

发数据                       选中芯片                                                       NFDATA=数据值
                              ALE,CLE设为低电平
                        在DATA0~DATA7上输出数据值
                                 发出一个写脉冲

读数据                         选中芯片                                                       val=NFDATA
                                  发出读脉冲 
                             读DATA0~DATA7的数据

 

主要寄存器:

UBOOT实际操作

可以使用UBOOT实际操作Nandflash

1. 读ID


                                        CPU对S3C2440的操作                              u-boot 中实现代码
选中                                   NFCONT的bit1设为0                      md.l 0x4E000004 1; mw.l 0x4E000004  1//写入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
          0xda
退出读ID的状态                 NFCMMD=0xff         mw.b 0x4E000008 0xff

2. 读内容: 读0地址的数据


使用UBOOT命令查看地址0的数据:
nand dump 0
Page 00000000 dump:
        17 00 00 ea 14 f0 9f e5  14 f0 9f e5 14 f0 9f e5

                                                  CPU对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

 

NandFlash编程

编程原理

nandflash的编程主要分别几步:

1.初始化 ,初始化主控芯片的nandflash控制器

2.识别芯片,读取ID

3.读数据  page单位

4.写数据  page单位

5.擦除   块block单位

 

Nand控制器具有时序输出,nandflash芯片也具有时序输入,所以要根据芯片的时序配置nandflash控制器的时序输出

Nandflash的CLE与ALE时序图与寄存器:

NandFlash在HCLK下,HCLK是100M,那么一个时钟周期10ns

 

flash芯片初始化时序以及时序周期

 

可以看出,在芯片时序图中,操作要求先上拉CLE/下拉CE/下拉ALE---下拉WE。

首先tCLS时间最小12ns,而tWP的最小时间也是12ns,所以CLE与WE可以同时上拉/下拉。对应2440的时序图,TACLS可以为0,所以NFCONF的[13:12]可以设置为0

再来看TWRPH0,表示的是WE下拉时间长度,对应flash时序图的tWP,最小12ns,根据计算公式10*(TWRPH0+1)>=12,TWRPH0>=1,取1即可

TWRPH1表示WE上拉后CLE/ALE延时下拉时间长度,对应flash时序图中tALH,最小5.根据计算公式得TWRPH1>=0.所以flash初始化:

void nand_init(void)
{
    /*设置时序*/
    NFCONF=(0<<12)|(1<<8)|(0<<4);
    /*始能,禁止片选,初始化ECC编码器*/
    NFCONT=(1<<0)|(1<<1)|(1<<4);
}

读取设备ID

接下来读取设备ID,内存大小

在nandflash芯片数据手册中有读取id时序图:

在时序图中,发送90h指令与00h地址后,芯片会返回厂家地址ECH,设备地址DAH,3rd字节,4rd字节,在第4字节中,[5:4]表示block大小,[1:0]表示page大小

由时序图可知,首先下拉片选CE,然后上拉CLE与WE,这时输入命令,再上拉WE,下拉CLE,命令输入结束

然后上拉ALE,下拉WE,输入地址,再上拉WE,下拉ALE。

2440中的NANDFLASH控制器会帮助我们进行时序的控制,只需将值写入NANDFLASH控制器寄存器即可。

添加读取id代码,并且编写测试函数:

#include "my_printf.h"
#include "s3c2440_soc.h"
void nand_init(void)
{
    /*设置时序*/
    NFCONF=(0<<12)|(1<<8)|(0<<4);
    /*始能,禁止片选,初始化ECC编码器*/
    NFCONT=(1<<0)|(1<<1)|(1<<4);
}

void nand_select(void)
{
    NFCONT&=~(1<<1);//始能片选
}

void nand_deselect(void)
{
    NFCONT|=(1<<1);
}

void nand_cmd(unsigned int cmd)
{
    volatile int i;
    NFCMD=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_chip_id(void)
{
    unsigned char buf[5]={0};
    nand_select();
    nand_cmd(0x90);
    nand_addr_byte(0x00);
    
    buf[0]=nand_data();
    buf[1]=nand_data();
    buf[2]=nand_data();
    buf[3]=nand_data();
    buf[4]=nand_data();

    nand_deselect();

    printf("maker id=0x%x\n\r",buf[0]);
    printf("device id=0x%x\n\r",buf[1]);
    printf("3rd byte=0x%x\n\r",buf[2]);
    printf("4rd byte=0x%x\n\r",buf[3]);
    printf("page size=%d kb\r\n",1<<(buf[3]&0x03));
    printf("block size=%d kb\r\n",(1<<((buf[3]>>4)&0x03))*64);
    printf("5rd byte=0x%x\n\r",buf[4]);
}

void nand_flash_test(void)
{
	char c;

	while (1)
	{
		/* 打印菜单, 供我们选择测试内容 */
		printf("[s] Scan nand flash\n\r");
		printf("[e] Erase nand flash\n\r");
		printf("[w] Write nand flash\n\r");
		printf("[r] Read nand flash\n\r");
		printf("[q] quit\n\r");
		printf("Enter selection: ");

		c = getchar();
		printf("%c\n\r", c);

		/* 测试内容:
		 * 1. 识别nand flash
		 * 2. 擦除nand flash某个扇区
		 * 3. 编写某个地址
		 * 4. 读某个地址
		 */
		switch (c)		 
		{
			case 'q':
			case 'Q':
				return;
				break;
				
			case 's':
			case 'S':
				nand_chip_id();
				break;

			case 'e':
			case 'E':
				break;

			case 'w':
			case 'W':
				break;

			case 'r':
			case 'R':
				break;
			default:
				break;
		}
	}
}

输出结果:

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值