JZ2440 NAND

设置好时序参数后,发送命令直接写NFCCMD,发送地址直接写NFADDR,写数据直接写NFDATA,读数据直接读NFDATA,控制器会发出相应的时序波形,从而控制NAND FLASH。

Ø  初始化

void nand_init(void)

{

#define  TACLS  0

#define  TWRPH0 1

#define  TWRPH1 0

         /*设置NAND FLASH的时序*/

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

         /*使能NAND FLASH控制器,初始化ECC,禁止片选*/

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

}

Ø  ID

片选->发送命令0x90->发送地址0x00->读五次->取消片选

Ø  读数据

注:2112 = 2048 + 64,2048为某一页page的数据,64位OOB

void nand_read(unsigned int addr, unsigned char *buf, unsigned int len)

{

         int i = 0;

         int page = addr / 2048;

         int col = addr & (2048 - 1);

         nand_select();

         while (i < len)

         {

                   /* 发出00h命令 */

                   nand_cmd(00);

                   /* 发出地址 */

                   /* col addr */

                   nand_addr_byte(col &0xff);

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

                   /* row/page addr */

                   nand_addr_byte(page &0xff);

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

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

                   /* 发出30h命令 */

                   nand_cmd(0x30);

                   /* 等待就绪 */

                   wait_ready();

                   /* 读数据 */

                   for (; (col < 2048)&& (i < len); col++)

                   {

                            buf[i++] =nand_data();                     

                   }

                   if (i == len)

                            break;

                   col = 0;

                   page++;

         }

         nand_deselect();   

}

此实验中,bin文件烧写到nandflash,从nand启动,上电后使用nand_read函数将程序从nand读到sdram,然后跳到sdram执行代码。如果程序执行正确,则nand_read函数正确。编译程序时需要把nand文件靠前,保证在前4k内容中包含nand函数。

int isBootFromNorFlash(void)

{

         volatile unsigned int *p = (volatileunsigned int *)0;

         unsigned int val = *p;

         *p = 0x12345678;

         if (*p == 0x12345678)

         {

                   /* 写成功, 对应nand启动 */

                   *p = val;

                   return 0;

         }

         else

         {

                   return 1;

         }

}

void copy2sdram(void)

{

         /* 要从lds文件中获得__code_start, __bss_start

          * 然后从0地址把数据复制到__code_start

          */

         extern int __code_start, __bss_start;

         volatile unsigned int *dest = (volatileunsigned int *)&__code_start;

         volatile unsigned int *end = (volatileunsigned int *)&__bss_start;

         volatile unsigned int *src = (volatileunsigned int *)0;

         int len;

         len = ((int)&__bss_start) -((int)&__code_start);

         if (isBootFromNorFlash())

         {

                   while (dest < end)

                   {

                            *dest++ = *src++;

                   }

         }

         else

         {

                   nand_init();

                   nand_read(src, dest, len);

         }

}

Ø  烧写与擦除

int nand_erase(unsigned int addr, unsigned int len)

{

         int page = addr / 2048;

         if (addr & (0x1FFFF))

         {

                   printf("nand_erase err,addr is not block align\n\r");

                   return -1;

         }

         if (len & (0x1FFFF))

         {

                   printf("nand_erase err,len is not block align\n\r");

                   return -1;

         }

         nand_select();

         while (1)

         {

                   page = addr / 2048;

                   nand_cmd(0x60);

                   /* row/page addr */

                   nand_addr_byte(page &0xff);

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

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

                   nand_cmd(0xD0);

                   wait_ready();

                   len -= (128*1024);

                   if (len == 0)

                            break;

                   addr += (128*1024);

         }

         nand_deselect();   

         return 0;

}

void nand_write(unsigned int addr, unsigned char *buf, unsigned int len)

{

         int page = addr / 2048;

         int col = addr & (2048 - 1);

         int i = 0;

         nand_select();

         while (1)

         {

                   nand_cmd(0x80);

                   /* 发出地址 */

                   /* col addr */

                   nand_addr_byte(col &0xff);

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

                   /* row/page addr */

                   nand_addr_byte(page &0xff);

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

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

                   /* 发出数据 */

                   for (; (col < 2048)&& (i < len); )

                   {

                            nand_w_data(buf[i++]);

                   }

                   nand_cmd(0x10);

                   wait_ready();

                   if (i == len)

                            break;

                   else

                   {

                            /* 开始下一个循环page*/

                            col = 0;

                            page++;

                   }

         }

         nand_deselect();   

}

猜你喜欢

转载自blog.csdn.net/hfutyyj/article/details/80075960