1-13 NandFlash的原理与实践

(本页笔记的详细实验代码,可参看这里:https://github.com/elvinsys/arm_tq2440/tree/master/1_uboot/1-13.nandflash

一、  NandFlash的原理解析

    1.  NandFlash一般充当的是嵌入式系统中存放数据的“硬盘”的角色。

    2.  分类

        SLC(Single Level Cell):单层式存储,在存储格上只存放一位数据

        MLC(Multe Level Cell)  :多层式存储,在存储格上则能存放两位数据

    3.  SLC与MLC的对比

        3.1  价格:MCL低于SLC

        3.2  速度:SLC是MLC的3倍

        3.3  使用寿命:SLC可擦写10万余次,MLC仅为1万余次

        3.4  功耗:SLC比MLC功耗低15%

    4.  NandFlash的编址方式:

            内存为统一编址,需要大量的地址线和数据线,NandFlash为独立编址,共用8根地址线,ARM核通过NandFlash控制器对NandFlash访问,通过8个专属寄存器来传递地址、命令以及数据。

    5.  NandFlash的地址结构:

(例如K9F2G08X0A这么一个型号的nandflash芯片) =  (2K + 64)B * 64 Page * 2048 Blocks = 2112Mbits


I/O     0     1       2        3        4        5       6        7

1st   A0   A1      A2     A3      A4     A5     A6      A7

2ed   A8   A9      A10   A11    L       L        L        L     Column Address

3rd   A0   A13   A14   A15   A16   A17   A18   A19

4th   A0   A21   A22   A23   A24   A25   A26   A27

5th   A0   L        L       L        L        L       L        L        Row Address


2kbytes       :  A0-A11    Column Address   列地址

128kPages:  A12-A28  Row Address         行地址

L   : must Low


    6.  信号引脚

       CLE(Command Latch Enable):命令锁存允许

        ALE(Address Latch Enable):地址锁存允许

        CE  :芯片选择

        RE  :读允许

       WE :写允许

        WP :在读写期间写保护

       R/B :读忙


二、  NandFlash驱动设计(读部分)

先touch nand.c   把nand.o加入到Makefile中

    1.  NandFlash的读写方式

        1.1  页读:通过页地址,读取2K整页数据

        1.2  随机读:通过行地址和列地址,读取某页某字节的数据

    2.  页读的实现方法:

        2.1  参考NandFlash的芯片手册,(搜索“operation”关键字),找出Read的时序图

            建立函数  void_PageRead(unsigned long addr, unsigned char *buff);/*  addr为页地址,buff为数据存放指针  */

        2.2  根据 I/O 引脚编写代码如下:

            2.2.1  /*  选中NandFlash芯片  */

#define NFCONF (*(volatile unsigned long*)0x4E000000)

void select_chip()
{
NFCONT &= ~(1<<1);
}

            2.2.2  /*  取消选中NandFlash芯片  */

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

            2.2.3  /*  清除RnB  */

#define NFSTAT (*(volatile unsigned char*)0x4E000020)

void clear_RnB()
{
NFSTAT |= (1<<2);
}       //写1置0,从低电平->高电平,自动置1

            2.2.4  /*  发送命令  */

#define NFCMMD (*(volatile unsigned char*)0x4E000008)

void send_cmd(unsigned cmd)
{
NFCMMD = cmd;
}

            2.2.5  /*  发送地址  */

#define NFADDR (*(volatile unsigned char*)0x4E00000C)

void send_addr(unsigned addr)
{
NFADDR = addr;
}

            2.2.6  /*  等待RnB  */

void wait_RnB()
{
while(!(NFSTAT&(1<<2)));
}

        2.3  NF_PageRead函数的实现

void NF_ReadPage(unsigned long addr, unsigned char* buff)
{
int i;
//选中nandflash
select_chip();

//清楚RnB
clear_RnB();

//发送指令0x00
send_cmd(0x00);

//发送两个列地址
send_addr(0x00);
send_addr(0x00);

//发送三个行地址
send_addr(addr&0xff);
send_addr((addr>>8)&0xff);
send_addr((addr>>16)&0xff);

//发送指令0x30
send_cmd(0x30);

//等待RnB
wait_RnB();


//读数据到指定地址
for(i = 0;i < 2048; i++)
{
buff[i] = NFDATA;
}

//取消选中nandflash
deselect_chip();

}

    3.  NandFlash的初始化

        3.1  方法描述

            3.1.1  设置NFCONF寄存器的三个参数TACLS [13:12],TWRPH0 [10:8],TWRPH1 [6:4]

                       (参考2440芯片手册6-3,对比Nandflash手册P20 command latch cycle)

                        TACLS->tCLS - twp

                        TWRPH0->twp

                        TWRPH1->tCLH

                        Duration = HCLK x TACLS > 0 ns                    TACLS = 1

                        Duration = HCLK x (TWRPH0 + 1) > 12ns    TWRPH0 = 2

                        Duration = HCLK x (TWRPH1 + 1) > 5 ns     TWRPH1 = 1

            3.1.2  设置NFCONT寄存器的两个参数

                        MODE         [0] 0:disable   1:enable     //应填1

                        Reg_nCE   [1] 0:enable select chip 1:disable  //填1

            3.1.3  对NandFlash进行复位(参考NandFlash手册的Reset Operation),具体代码如下:

void nand_rest()
{
//选中nandflash
select_chip();

//清楚RnB
clear_RnB();

//发送指令0xff
send_cmd(0xff);


//等待RnB
wait_RnB();

//取消选中nandflash
deselect_chip();
}

        3.2  NandFlash初始化的实验代码如下:

#define NFCONF (*(volatile unsigned long*)0x4E000000)

#define TACLS               (1<<12)
#define TWRPH0              (2<<8)
#define TWRPH1              (1<<4)

void nand_init()
{
NFCONF |= (TACLS | TWRPH0 | TWRPH1);
NFCONT |= (NAND_ENABLE | NAND_SELECT_DISABLE);
nand_rest();
}

    4.  把NandFlash的数据复制到SDRAM的代码实现:

void NandFlash_to_SDRAM(unsigned long nand_addr, unsigned char* sdram_addr, int size)
{//size原来定义为unsigned size,虽然编译能过,但下载后就无法点灯
int i;
for(i = (nand_addr>>11); size >0;)
{
NF_ReadPage(i,sdram_addr);
sdram_addr += 2048;
size -= 2048;
i++;
}
}

    5.  在start.S中修改 copy_ram标号的内容

copy_ram:
mov r0, #0x00
ldr r1, =_start
ldr r2, =bss_end
sub r2, r2, r1

mov ip, lr
bl NandFlash_to_SDRAM
mov lr, ip
mov pc, lr

    6.  因为在copy_ram中需要用到堆栈,因此在start.S中,把copy_ram的标号前,加入bl init_stack 和 bl init_nand


三、  NandFlash驱动设计(写部分)

    1.  NandFlash写数据的代码实现:(参考手册“Page Program Operation”)

int NF_WritePage(unsigned long addr, unsigned char* buff)
{
int i, ret;
//选中nandflash
select_chip();

//清楚RnB
clear_RnB();

//发送指令0x80
send_cmd(0x80);

//发送两个列地址
send_addr(0x00);
send_addr(0x00);

//发送三个行地址
send_addr(addr&0xff);
send_addr((addr>>8)&0xff);
send_addr((addr>>16)&0xff);

//写数据到指定地址
for(i = 0;i < 2048; i++)
{
NFDATA = buff[i];
}

//发送指令0x10
send_cmd(0x10);

//等待RnB
wait_RnB();

//发送指令0x70
send_cmd(0x70);

//接收结果
ret = NFDATA;

//取消选中nandflash
deselect_chip();

return ret;
}

    2.  对NandFlash进行擦除操作的实现代码:(参考NandFlash手册中的“Block Erase Operation”整块擦除的内容)

int NF_Erase(unsigned long addr)
{
int ret;
//选中nandflash
select_chip();

//清楚RnB
clear_RnB();

//发送指令0x60
send_cmd(0x60);

//发送三个行地址
send_addr(addr&0xff);
send_addr((addr>>8)&0xff);
send_addr((addr>>16)&0xff);

//发送指令0xd0
send_cmd(0xd0);

//等待RnB
wait_RnB();

//发送指令0x70
send_cmd(0x70);

//接收结果
ret = NFDATA;

//取消选中nandflash
deselect_chip();

return ret;
}


四、  最后,在main.c中加入测试代码:

NF_Erase(64*5);

led_off();

buff[0] = 100;

NF_WritePage(0xa0000, buff);

buff[0] = 10;

NF_ReadPage(0xa0000, buff);

if(buff[0] == 10)
{
led_off();
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值