Nand Flash变硬盘

Nand Flash原理解析

Nand Flash的分类:
根据物理结构上的区别,Nand Flash主要分为如下两类:
SLC (Single Level Cell):单层式存储
MLC (Multi Level Cell):多层式存储
SLC在存储格上只存一位数据,而MLC则存放两位数据

MLC对比SLC:
1、价格:
由于MLC采用了更高密度的存储方式,因此同容量的MLC价格上远低于SLC。
2、访问速度:
SLC的访问速度一般要比MLC快3倍以上。
3、使用寿命:
SLC能进行10万次的擦写,MLC能进行1万次。
4、功耗:
MLC功耗比SLC高15%左右。

编址方式:
内存是统一编址的,有地址线和数据线来访问。
flash不是统一编址的,他是独立编址,CPU内部有nand flash控制寄存器,通过寄存器先传地址,再传命令。

控制类引脚作用:
1. CLE(Command Latch Enable): 命令锁存允许
2. ALE(Address Lactch Enable): 地址锁存允许
3. CE:芯片选择
4. RE:读允许
5. WE:写允许
6. WP:在写或擦除期间,提供写保护
7. R/B:读/忙

Nand Flash读操作

一个设备要使用,一般需要先初始化,nandflash也不例外。
任何一个flash使用,都要先选中,然后再清除选中。
在调用初始化flash的c语言之前,要先把栈设置好。

汇编中调用C语言函数,参数由 r0 r1 r3 寄存器来传递。

代码举例:
1、将代码从flash拷贝到ram中

copy_to_ram: 
    mov r0,#0             @调用C语言函数来拷贝
    ldr r1,=_start
    ldr r2,=bss_end
    sub r2,r2,r1

    mov ip,lr
    bl nand_to_ram
    mov lr,ip

    mov pc,lr

2、nand.c文件

#define NFCONF   (*((volatile unsigned long*)0x70200000))
#define NFCONT   (*((volatile unsigned long*)0x70200004))
#define NFCMMD   (*((volatile unsigned char*)0x70200008))
#define NFSTAT   (*((volatile unsigned char*)0x70200028))
#define NFADDR   (*((volatile unsigned char*)0x7020000c))
#define NFDATA   (*((volatile unsigned char*)0x70200010))

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

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

void clean_RnB()
{
    NFSTAT |= (1<<4);
} 
void nand_cmd(unsigned char cmd)
{
    NFCMMD = cmd;   
}

void wait_RnB(void)
{
    while(!(NFSTAT & 0x1));
}

void nand_addr(unsigned char addr)
{
    NFADDR = addr;
}

void nand_reset(void)
{
    /* 选中 */
    select_ship();

    /* 清除RnB */
    clean_RnB();

    /* 发出复位信号 */
    nand_cmd(0xff);

    /* 等待就绪 */
    wait_RnB();

    /* 取消选中 */
    delselect_ship();
}

void nand_init(void)
{ 
/*
HCLK的频率为100MHZ,周期就为10ns
TACLS > 0 ns
TWRPH0  > 15ns
TWRPH1 > 5ns

TACLS的值 = HCLK x TACLS > 0ns
TWRPH0的值 = HCLK x (TWRPH0 + 1) > 15ns
TWRPH1的值 = HCLK x (TWRPH1 +1) > 5ns 
*/

    /* 设置时间参数 */
    #define TACLS  1
    #define TWRPH0 2
    #define TWRPH1 1

    NFCONF &= ~((7<<12)|(7<<8)|(7<<4));
    NFCONF |= (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);

    /* 使能 nandflash controller*/
    NFCONT = 1 | (1<<1);

    /* 复位 */
    nand_reset();
}

void NF_PageRead(unsigned long addr,unsigned char* buff)
{
    int i;  
    /* 选中芯片 */
    select_ship();

    /* 清除RnB */
    clean_RnB();

    /* 发出命令0x00 */
    nand_cmd(0x00);

    /* 发出列地址 */
    nand_addr(0x00);
    nand_addr(0x00);

    /* 发出行地址 */
    nand_addr(addr&0xff);
    nand_addr((addr >>8 ) & (0xff));
    nand_addr((addr >>16 ) & (0xff));

    /* 发出命令0x30 */
    nand_cmd(0x30);

    /* 等待就绪 */
    wait_RnB();

    /* 读数据 */
    for(i = 0; i<1024*4; i++)
    {
        buff[i] = NFDATA;
    }

    /* 取消片选 */
    delselect_ship();  
}

void nand_to_ram(unsigned long start_addr,unsigned char* sdram_addr,int size)
{
    /* i为页号、sdram_addr为内存中的位置、size拷贝数据的大小 */
    int i;

    /*
    S3C6410启动时拷贝的8K代码不是存储在Nand flash的第一页上,
    而是位于nand flash的前4页上,每页2K,总共8K,  
    */
    for (i = 0; i < 4; i++, sdram_addr+=2048) 
    {
        NF_PageRead(i,sdram_addr);
    }

    size -= 1024*8;

    for( i=4; size>0;)
    {
        NF_PageRead(i,sdram_addr);  
        size -= 4096;
        sdram_addr += 4096;
        i++;
    }          
}

Nand Flash写操作

写的操作与读操作类似,最重要的是找到数据手册中的时序图,flash使用的是HCLK。

代码举例:

int NF_Erase(unsigned long addr)
{
    int ret;
    //选中flash芯片
    select_ship();

    //清除RnB
    clean_RnB();

    //发送命令60
    nand_cmd(0x60);

    //发送行地址(3个周期)
    nand_addr(addr&0xff);
    nand_addr((addr >>8 ) & (0xff));
    nand_addr((addr >>16 ) & (0xff));

    //发送命令D0
    nand_cmd(0xD0);

    //等待RnB
    wait_RnB();

    //发送命令70
    nand_cmd(0x70);

    //读取擦除结果
    ret = NFDATA;

    //取消选中flash芯片
    delselect_ship();

    return ret;
}

int NF_WritePage(unsigned long addr,unsigned char* buff)
{
    int ret,i;

    //选中flash芯片
    select_ship();

    //清除RnB
    clean_RnB();

    //发送命令80
    nand_cmd(0x80);

    //发送列地址(2个周期)
    nand_addr(0x00);
    nand_addr(0x00);

    //发送行地址(3个周期)
    nand_addr(addr&0xff);
    nand_addr((addr >>8 ) & (0xff));
    nand_addr((addr >>16 ) & (0xff));

    //写入数据
    for(i=0;i<1024*4;i++)
    {
        NFDATA = buff[i];   
    }

    //发送命令10
    nand_cmd(0x10);

    //等待RnB
    wait_RnB();

    //发送命令70
    nand_cmd(0x70);

    //读取写入结果
    ret = NFDATA;

    //取消选中flash芯片
    delselect_ship();

    return ret;
}

测试代码:

    NF_Erase(128*1+1);
    buf[0] = 100;
    NF_WritePage(128*1+1,buf);

    buf[0] = 10;
    NF_PageRead(128*1+1,buf);   
    if( buf[0] == 100 )
        lightLED();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值