NandFlash操作详解(三)

代码正确性验证:

         验证代码的正确性可以使用先写入特定字符,然后在读出来的方法验证。

实验板:MINI2440 256M

首先下载一个可用的u-boot到NorFlash中,用于查看NandFlash中的数据。

然后以NorFlash启动进入u-boot,使用tftp工具或者其他工具把测试程序下载到NandFlash的0地址。以NandFlash启动查看测试结果。

 

测试文件main.c:                                                                                                                                                                                                                                                                  

int xboot_main()

{

         int num = 0;

         int a = 1;

         int b = 2;

         char buf[2048] = {"hello NandFlash"};

         char buf2[2048] = {};

         uart_init();

 

         printf("start nandflash read/write\n\r");

 

         NF_Erase(0x32345);

         NF_WritePage(0x32345,buf);

         NF_PageRead(0x32345,buf2);        

         printf("\n\n%s\n\r",buf2);

 

         while(1)

         {

                   printf("\n***************************************\n\r");

                   printf("\n****************XBOOT*****************\n\r");

                   printf("1:Download Linux Kernel from TFTP Server!\n\r");

                   printf("2:Boot Linux from RAM!\n\r");

                   printf("3:Boot Linux from Nand Flash!\n\r");

                   printf("\n Plese Select:");

            

                   scanf("%d",&num);

   

                   switch (num)

                   {

                            case 1:

                            //tftp_load();

                            break;

           

                            case 2:

                            //boot_linux_ram();

                            break;

           

                            case 3:

                            //boot_linux_nand();

                            break;

           

                            default:

                            printf("Error: wrong selection!\n\r");

                            break;      

                   }

         }       

         return 0;

}

 

完整的nand.c文件:

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

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

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

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

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

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

 

#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;

        

         //int col = addr % 2048;

         //int page = addr / 2048;

         int col = 0x0;

         int page = addr;

 

         //选中nandflash芯片

         select_chip();

        

         //清除RnB

         clear_RnB();

        

         //发送命令0x00

         send_cmd(0x00);

        

         send_addr(col & 0xff);

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

 

         send_addr(page & 0xff);

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

         send_addr((page >> 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 page = start_addr / 2048;

         for(;size>0;)

         {

             NF_PageRead(page,sdram_addr);

             size -= 2048;

             sdram_addr += 2048;

             page++;

         }

}

 

int NF_Erase(unsigned long addr)

{

         int ret;

         unsigned int page = addr/2048;

        

  //选中flash芯片

         select_chip();

        

         //清除RnB

         clear_RnB();

        

         //发送命令0x60

         send_cmd(0x60);

        

         //发送行地址

         send_addr(page&0xff);

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

         send_addr((page>>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)

{

         unsigned int i,ret = 0,page,col;

         col = addr % 2048;

         page = addr /2048;

         //选中nandflash

         select_chip();

        

         //清除RnB

         clear_RnB();

        

         //发送0x80命令

         send_cmd(0x80);

        

         //发送2个列地址

         /* 这种写法ok

         send_addr(col & 0xff);

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

         send_addr(page & 0xff);

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

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

         */

 

        

         send_addr(addr & 0xff);         // a0~a7

         send_addr((addr >> 8) & 0x7);   // 以程序角度看 a8~a10

 

         send_addr((addr >> 11) & 0xff); // 以程序角度看 a12~a19

         send_addr((addr >> 19) & 0xff); // 以程序角度看 a20~a27

         send_addr((addr >> 27) & 0xff); // 以程序角度看 a28   

        

/*     wrong 移位错误

         send_addr(addr & 0xff);         // a0~a7

         send_addr((addr >> 8) & 0x7);   // 以程序角度看 a8~a10

 

         send_addr((addr >> 12) & 0xff); // 以程序角度看 a12~a19

         send_addr((addr >> 20) & 0xff); // 以程序角度看 a20~a27

         send_addr((addr >> 28) & 0xff); // 以程序角度看 a28   

*/

         //发送数据

         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;

}

 

 

使用到的命令:

tftp 30000000 xboot.bin; nand erase 0 10000; nand write 30000000 0 10000                                                                                                                                            

下载成功后把把拨码开关拨到Nand启动,使用命令:

reset

执行完reset后看到:

可以看到NandFlash已经能正常写入并读取了,安全起见,再来使用u-boot查看一下NandFlash中的情况:

以Nor启动进入u-boot:

nand read 33000000 0x32000 10000; md.b 33000000 100                                                                                                                                                                              

回车

回车

回车

回车,可以看到:



这就完全可以清晰的看到NandFlash中的值了。

 

移植u-boot的过程中,为了实现NandFlash启动会使用一段实现u-boot.bin从NandFlash拷贝到SDRAM的代码,学习完上述NandFlash的操作再去看那段代码就没有任何难度了。

 

 

完整工程下载地址:http://download.csdn.net/detail/doccode/8914847

使用到的u-boot.bin下载地址:http://download.csdn.net/detail/doccode/8914859

 

 

 


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值