nandflash驱动设计

来源:互联网 发布:php 模拟post 编辑:IT博客网 时间:2020/02/23 12:27

一:Nandflash驱动设计写的流程

1, 知道要读的东西  即:芯片选择为nandflash 方式:NFCOPNT-》对应位使有效;

2  清除RnB 即:使其进入空闲状态 方式:NFCONF—》对应位是空闲(清除要写入1才能变0

3  发送页读指令周期0x00 方式: NFCMMD=0x00

4  发送列地址和行地址 方式:NFADDR=addr

    注: 行地址是页号,列地址是页内偏移,若是页读则列地址发送0x00就行

        若是随机读取则需要定位列地址和行地址

发送页读命令周期0x30 方式:NFCMMD=0x30

等待RnB  ;等待CPU将前面的工作完成之后使RnB进入忙 方式:检测NFSTAT      中对应位是否为1,为1等待结束,为0等待继续

读取数据 方式: 将NFDATA中的数据传给制定缓冲 eg buff[i]=NFDATA

取消nandflash芯片选择 方式: NFCONT 使对应为无效

我理解的发送两次页读命令周期:第一次发送0x00 是进行读前的准备工作 即找读的地址 等   第二次发送0x30 是进行真正的将数据从nandflash中读取到缓冲中  同理到其他的周期命令中:一般第一次是准备工作,第二次是进行工作

 

二: 一切工作看似已经完成,其实还有,这个可能还是用与其他大部分的驱动程序。那就 是在使用一个设备时要先初始化这个设备,在次 我们要初始化的是nandflash

其实在之前初始化的东西很多,比如在用C编写的话要初始化堆栈。还有要初始化SDRAM    总之一句话那就是用到什么就要先初始化什么

 

初始化NFCONFF 其实是初始化NFCONF中的三个位即 TACLS TWRPH0 TWRPH1

  因为他们三个基本决定了读取数据的一些重要时间:(具体大小需要按照不同类型的nandflash进行计算,但一般原则是它们的值大一点比较稳定)

2  初始化NFCONT 设置REG_nCE位为1 MOND位为即 使片选信号无效

并开启控制器

复位  

选中nandflash芯片 同上

清除RnB 同上

发送命令 0xffreset 命令周期)

等待 RnB 同上

取消选中nandflash

三: 在汇编语言中即程序入口处调用读取页的函数,并用相应的寄存器传参;

四:nandflash驱动的写和读差不多:

参考的芯片手册与文档:S3C2440文档;K9GAG08U0Dnandflash芯片文档)

6410210都差不多就是寄存器地址与相应的位需要变一下;

代码如下:

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

#define NFCONT (*(volatile unsigned long*)0x4E000004)

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

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

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

#define NFDATA (*(volatile unsigned char*)0x4E000010)

 

#define TACLS 1

#define TWRPH0 2

#define TWRPH1 1

 

 

void select_chip()

{

    NFCONT &= ~(1<<1);

}

 

void deselect_chip()

{

    NFCONT |= (1<<1);

}

 

void clear_RnB()

{

   NFSTAT |= (1<<2); 

}

 

void send_cmd(unsigned cmd)

{

     NFCMD = cmd;

}

 

void send_addr(unsigned addr)

{

     NFADDR = addr;

}

 

void wait_RnB()

{

   while (!(NFSTAT&(1<<2)))

   {

       ;

   }

}

 

void nand_reset()

{

    //选中flash

    select_chip();

    

    //清除RnB

    clear_RnB();

    

    

    //发送0xff命令

    send_cmd(0xff);

    

    

    //等待RnB

    wait_RnB();

    

    //取消选中flash

    deselect_chip();

}

 

void nand_init()

{

    //初始化NFCONF

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

    

    //初始化NFCONT

    NFCONT = (1<<0) | (1<<1);

    

    //复位

    nand_reset();

}

 

void NF_PageRead(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();

}

 

 

void nand_to_ram(unsigned long start_addr, unsigned char* sdram_addr, int size)

{

     int i;

     

for( i=(start_addr >>11); size>0;)

{

    NF_PageRead(i,sdram_addr);

    size -= 2048;

    sdram_addr += 2048;

    i++;

}

}

 

void NF_Erase(unsigned long addr)

{

int ret;

        //选中flash芯片

select_chip();

//清除RnB

clear_RnB();

//发送命令0x60

send_cmd(0x60);

//发送行地址

send_addr(addr&0xff);

send_addr((addr>>8)&0xff);

send_addr((addr>>16)&0xff);

//发送命令D0

send_cmd(0xD0);

//等待RnB

wait_RnB();

//发送命令0x70

send_cmd(0x70);

//读取擦除结果

ret = NFDATA;

//取消选中flash芯片

deselect_chip();

return ret;

}

 

int NF_WritePage(unsigned long addr, unsigned char* buff)

{

int ret;

int i;

//选中flash芯片

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;

//取消选中flash芯片

deselect_chip();

return ret;

}

0 0
原创粉丝点击