tiny6410裸机实验第6章--------------NAND(初始化代码及NAND操作)

来源:互联网 发布:中原 知乎 编辑:程序博客网 时间:2024/06/11 11:55


【说明】

             前面我们已经说明了初始化NAND控制器的原理,这一节就是源代码了,这个源代码不是用的友善的源代码,因为我的NAND FLASH 是8KB块的。友善给的源代码是2KB的。这个代码是一位网友提供的。初始化步骤就是按前面的原理来的。这节还会介绍读写NAND的操作

 

 

【初始化代码】

              其中的nand_reset 在下面,它和初始化没关系的。

#define GPOCON (*(volatile unsigned long*)(0x7F008140))#define GPOPUD (*(volatile unsigned long*)(0x7F008148))#define GPPCON (*(volatile unsigned long*)(0x7F008160))#define GPPPUD (*(volatile unsigned long*)(0x7F008168))#define TACLS 7#define TWRPH0 7#define TWRPH1 7void nand_init(){        GPOCON = (GPOCON & ~0xf) | 0xa;//nCS[3:2]        GPOPUD &= ~0xf;        GPPCON = (GPPCON & ~(0xfff << 4)) | (0xaaa << 4);//nWAIT, FALE, FCLE,        GPPPUD &= ~(0xfff << 4);//FWEn, FREn, FRnB        MEM_SYS_CFG &= ~(1<<1);        NFCONF &= ~((0x7<<4)|(0x7<<8)|(0x7<<12)|(1<<30));        NFCONF |= (TWRPH1<<4)|(TWRPH0<<8)|(TACLS<<12);        NFCONT |= 1;        NFCONT &= ~(1<<16);        nand_reset();}


【选中和取消片选】

              1】原理

                  这个寄存器我们前面见过的,它里面就有控制片选信号的位                                               

              

                因为我们的片选信号用的是XM0CSN2,所以用下面的位

                

             2】代码

                

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


 

【发送命令】

             1】原理

                     一眼就看到这个寄存器了!        

                 

                     可是该往里面写什么呢。。命令是些什么呢?在NAND的芯片手册上有相应的命令的编号,我们看看!

                    

            2】源代码

                 

void nand_cmd(unsigned char cmd){        NFCMMD = cmd;}


 

【发送地址】

                 1】原理

                      显然要用这个寄存器

                     

                      但是一样的,我们要怎么发地址呢,还记得吗,我们数据地址命令都只用同样一组线,而且只有8根,,显然地址要分多次发送

                     在NAND 芯片手册中我们找到了,没错!一次地址要发送5个周期。。。。

                      

             2】源代码

 

void nand_addr(unsigned long addr){        unsigned long row = addr/PAGE_SIZE;        unsigned long column = addr%PAGE_SIZE;        NFADDR = column&0xFF;        NFADDR = (column>>8)&0xFF;        NFADDR = row&0xFF;        NFADDR = (row>>8)&0xFF;        NFADDR = (row>>16)&0xFF;}


 

【等待就绪】

                   1】原理

                             还记得我们原理图中的RNB吗,没错,就是和这个寄存器的第一位直接挂钩

                           

                           

                   2】源代码

                           

void nand_ready(){        while((NFSTAT&0x1) == 0);}


 

【RESET】

                   从上边知道要RESET就要发送0XFF命令,我们直接来看代码,体会一下各个函数如何组合使用

void nand_reset(){        nand_select();        nand_cmd(0xff);        nand_ready();        nand_deselect();}


 

 

 

【读,擦除,写】

              我觉得直接放源代码就能懂了。。没什么新东西,唯一要注意的就是要先擦除才能写。

              另外就是NAND 是按页来存储的,我的NAND 是一页8KB。。发送一次地址,NAND 会为你准备一整页的数据,读这一整页不需要重新发地址。。

int nand_read(unsigned int nand_start, unsigned int ddr_start, unsigned int len){        unsigned long rest = len;        unsigned long addr = nand_start;        unsigned long page;        unsigned char *dest = (unsigned char *)ddr_start;        int i;        nand_select();        while(rest > 0){                nand_cmd(0x00);                nand_addr(addr);                nand_cmd(0x30);                nand_ready();                page = rest>PAGE_SIZE?PAGE_SIZE:rest;                for(i = 0; i != page; ++i){                        *dest++ = NFDATA;                }                rest -= page;                addr += page;        }        nand_deselect();        return 0;}void nand_erase(unsigned long addr){        int page = addr/PAGE_SIZE;        nand_select();        nand_cmd(0x60);        NFADDR = page&0xff;        NFADDR = (page>>8)&0xff;        NFADDR = (page>>16)&0xff;        nand_cmd(0xd0);        nand_ready();        nand_deselect();}void nand_write(unsigned int nand_start, unsigned char * buf, unsigned int len){        unsigned long count = 0;        unsigned long addr  = nand_start;        int i = nand_start % PAGE_SIZE;        nand_select();        while (count < len)        {                nand_cmd(0x80);                nand_addr(addr);                for (; i < PAGE_SIZE && count < len; i++)                {                        NFDATA = buf[count++];                        addr++;                }                nand_cmd(0x10);                nand_ready();                i = 0;        }        nand_deselect();}


 

【真正的重定位】

                     这下好了,我们可以使用NAND 了,,那么我们就可以写个函数,把程序从NAND 中复制到DDR中了。由于复制的时候前4页要特殊处理(前4页每页2K)后面的就按页大小来复制咯。。代码如下。。用来代替前一章的复制函数

void copy2ddr(unsigned long length){        unsigned long rest = length;        unsigned long size;        unsigned long i;        for(i = 0; i != 4; ++i){                size = rest>2048?2048:rest;                nand_read(PAGE_SIZE*i, 0x50000000+i*2048, size);                rest -= size;                if(rest == 0)                        return;        }        nand_read(PAGE_SIZE*4, 0x50000000+PAGE_SIZE, rest);}


 

0 0
原创粉丝点击