zoukankan      html  css  js  c++  java
  • Nand flash code

      (1)流水灯

         

       1>我们来看原理图

            

          

         

         

       2>datasheet

     

          

       

          

         

      3>leds.c

          

         #define GPFCON  (*(volatile unsigned long *)0x56000050)  //address

         #define GPFDAT  (*(volatile unsigned long *)0x56000054)

      

         #define GPF4_reset (3<<(4*2))

         #define GPF5_reset (3<<(5*2))

         #define GPF6_reset (3<<(6*2)) //reset

     

         #define GPF4_out  (1<<(4*2))

         #define GPF5_out  (1<<(5*2))

         #define GPF6_out  (1<<(6*2))//output

         void Delay_ms(volatile unsigned long ms);

         int main(void)

     {

       GPFCON &=~(GPF4_reset | GPF5_reset | GPF6_reset);

       GPFCON |= (GPF4_out | GPF5_out | GPF6_out);

         

       while(1)

     {

        GPFDAT &=~(1<<4);

        Delay_ms(30000);

        GPFDAT |=(1<<4);//led1

       

        GPFDAT &=~(1<<5);

        Delay_ms(30000);

        GPFDAT |=(1<<5);//led2

        GPFDAT &=~(1<<6);

        Delay_ms(30000);

        GPFDAT |=(1<<6);//led3

       return 0;

    }

         void Delay_ms(volatile unsigned long ms)

    {

       for(; ms>0; ms--);

    }

     

      (2)由于我们的程序所占用的空间会出现大于s3c2440的cpu的sram的空间,所以内存无法满足我们的需求,就需要在片外内存中进行运行。这里通过一个链接脚本将一部分程序放在nand flash的前4k的地方,将另一部分放在nand flash 的4k以后,这样的话,我们将nand flash的4K以后的程序拷贝到sram中进行运行就可以的。

         

      在开发板在nand flash模式下启动,开发板只能将前4K的程序拷贝到sram中运行。

      链接脚本:nand.lds

       SECTION{

         first   0x00000000  : {nand.o init.o crt.o}

         second  0x30000000  : AT(4096) {leds.o}

    }

      

     (3) nand.c

        

       #define  LANGE_PAGE

       typedef unsigned int  uint32;

       //s3c2440控制寄存器

      typedef struct{

         uint32  NFCONF;  //nand flash 配置寄存器

         uint32  NFCONT;  //nand flash 控制寄存器(s3c2410没有此寄存器)

         uint32  NFCMMD;  //nand flash 命令寄存器

         uint32  NFADDR;  //nand flash 地址寄存器

         uint32  NFDATA;  //nand flash 数据寄存器

         uint32  NFMECCD0; 

         uint32  NFMECCD1;

         uint32  NFSECCD;

         uint32  NFSTAT;  //状态寄存器

         uint32  NFESTAT0;

         uint32  NFESTAT1;

         uint32  NFMECC0;

         uint32  NFMECC1;

         uint32  NFSECC;

         uint32  NFSBLK;

         uint32  NFEBLK;

    }s3c2440_NAND;

      

       //s3c2410寄存器

      typedef struct{

        

        uint32  NFCONF;

        uint32  NFCMD:

        uint32  NFADDR;

        uint32  NFDATA;

        uint32  NFSTAT;

        uint32  NFECC;

    }s3c2410_NAND;

      typedef struct{

        void (*nand_reset)(void); //复位

        void (*nand_select_chip)(void);//片选信号

        void (*write_cmd)(unsigned int cmd); //写命令

        void (*nand_wait)(void);

        void (*write_addr)(unsigned int addr);//写地址

        unsigned char (*read_data)(void);//读地址

        void (*nand_deselect_chip)(void);//取消片选信号,节能

    }t_nand_chip;

       t_nand_chip  nand_chip;

       s3c2440_NAND * s3c2440_nand =(s3c2440_NAND*)0x4e000000;

       s3c2410_NAND * s3c2410_nand =(s3c2410_NAND*)0x4e000000;  //NFCONF的地址0x4e000000

       

       void s3c2410_nand_select_chip(void)

      {

        int i;

        s3c2410_nand->NFCONF &=~(1<<11);  //nFCE==0片选

        for(i=0;i<10.i++); //等待

    }

       

       void s3c2410_write_cmd(unsigned int cmd)

     {

         volatile unsigned char *p =(volatile unsigned char *)s3c2410_nand->NFCMD;

         *p=cmd;

    }

      void s3c2410_nand_wait(void)

     {

         int i;

         volatile unsigned char *p =(volatile unsigned char *)s3c2410_nand->NFSTAT;

         while(!(*p & 1)); //是否忙碌   //1--ready  0--busy

         

         for(i=0;i<10;i++);

    }

      void s3c2410_write_addr(unsigned int addr)

     {

         int i;

         volatile unsigned char *p =(volatile unsigned char *)s3c2410_nand->NFADDR;

         *p=addr&0xff;  /*A0-A7 */

         for(i=0;i<10;i++);

         *p=(addr>>9)&0xff;/*A9-A16 */

         for(i=0;i<10;i++);

         *p=(addr>>17)&0xff; /*A17-A24 */

         for(i=0;i<10;i++);

         *p=(addr>>25)&0x01; //A25

         for(i=0;i<10;i++);

    }

      unsigned char s3c2410_read_data(void)

     {

         volatile unsigned char *p =(volatile unsigned char *)s3c2410_nand->NFDATA;

         return *p;

    }

      void s3c2410_nand_deselect_chip(void)

     {

         s3c2410_nand->NFCONF |=(1<<11);

     }

      void s3c2410_nand_reset(void)

      {

         s3c2410_nand_select_chip();

         s3c2410_write_cmd(0xff);  //针对不同的nand flash 对应的nand falsh所要求nand控制器发出的命令有所不同 

         s3c2410_nand_wait();

         s3c2410_nand_deselect_chip();

    //s3c2440

      void s3c2440_nand_select(void)

      {

         int i;

         s3c2440_nand->NFCONT &=~(1<<1);

         for(i=0;i<10;i++);

    }

      void s3c2440_write_cmd(unsigned int cmd)

     {

         volatile unsigned char *p =(volatile unsignd char *)s3c2440_nand->NFCMMD;

         *p =cmd;

     }

      void s3c2440_nand_wait(void)

      {

         int i;

         volatile unsignd char *p=(volatile unsigned char *)s3c2440_nand->NFSTAT;

         while(!(*p & 1)); //判断是否忙碌

         for(i=0;i<10;i++);

    }

      void s3c2440_write_addr(unsigned int addr)//小页--521byte (K9F1208U0M)

      {

         int i;

         volatile unsigned char *p=(volatile unsigned char *)s3c2440_nand->NFADDR;

         *p=addr&0xff;     //A0-A7共8根线,可寻址2^8=256byte --半页(通过不同的命令 00h--上半页,01h--下半页)

         for(i=0;i<10;i++);

         *p=(addr>>9)&0xff;

         for(i=0;i<10;i++);

         *p=(addr>>17)&0xff;

         for(i=0;i<10;i++);

         *p=(addr>>25)&0x01;  //A9-A25 共17根线,可寻址 2^17=2^7k=4(层)*1024(块)*32(页)=2^7k page

         for(i=0;i<10;i++);

    }

        

       void s3c2440_write_addr_lp(unsigned int addr)//大页--2K(512*4)(K9F2G08x0A)

     {

         int i;

         int col,row;//col分两次,row分三次发送

         volatile unsigned char *p = (volatile unsigned char *)s3c2440->NFADDR;

         col=addr &(2048-1);  //addr & (11111111111)--取低11位

         row=addr/2048;   //取高位 --(2048==一页的大小)

         *p=col &0xff; /* A0-A7*/

         for(i=0;i<10;i++);

         *p=col & 0x0f;  /* A8-A11*/  --A0==A11共12根线,可寻空间2^12=2*2K,而一页是1K,留有余量,A11用来访问spare区域,也就是      for(i=0;i<10;i++);             -- oob区域用来存放校验信息, spare区域并不在编址范围内,需要使用A11控制访问

         *p=row & 0xff; /* A12-A19*/

         for(i=0;i<10;i++);

         *p=row & 0xff; /* A20-A27*/

         for(i=0;i<10;i++);

         *p=row & 0xff;  /* A28-A29*/  --A12==A28共17根线,可寻空间2^18=2^8k=2(层)*1024(块)*64(页)=2^7k page,同时留有                                    --余量,用来兼容大容量flash

    }

        

         unsigned char s3c2440_read_data(void)

     {

         volatile unsigned char *p=(volatile unsigned char *)s3c2440_nand->NFDATA;

         return 0;

     } 

      void s3c2440_nand_deselect_chip(void)

     {

         s3c2440_nand->NFCONT |=(1<<1);

    }

      void s3c2440_nand_reset(void)

     {

         s3c2440_nand_select_chip();

         s3c2440_write_cmd(0xff); 

         s3c2440_nand_wait();

         s3c2440_nand_deselect_chip();

     }

         GSTATUS1是芯片的ID,对于不同的芯片有对应的ID,s3c2440的ID是0x32440001,s3c2410的ID是0x32410000或0x32410002

       s3c2440的ID:

        

     

       s3c2410的ID:

       

      //nand初始化

      void nand_init(void)

     {

         #define  TACLS    0

         #define  TWRPH0   3

         #define  TWRPH1   0

       if((GSTATUS1==0x32410000)||(GSTATUS1==0x32410002)) //s3c2410

        {

           nand_chip.nand_reset =s3c2410_nand_reset;

           nand_chip.nand_select_chip =s3c2410_nand_select_chip;

           nand_chip.write_cmd =s3c2410_write_cmd;

           nand_chip.nand_wait =s3c2410_nand_wait;

           nand_chip.write_addr =s3c2410_write_addr;

           nand_chip.read_data =s3c2410_read_data;

           nand_chip.nand_deselect_chip =s3c2410_nand_deselect_chip;

           

           

           //使能nand flash控制器

           //初始化ECC

           //禁止片选信号

           //设置时序

           s3c2410_nand->NFCONF = (1<<15)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);

        }

       else                   //s3c2440

        {

           nand_chip.nand_select_chip =s3c2440_nand_select_chip;

           nand_chip.write_cmd =s3c2440_write_cmd;

           nand_chip.nand_wait =s3c2440_nand_wait;

         #ifdef  LANGE_PAGE

           nand_chip.write_addr =s3c2440_write_addr_lp;

         #else

           nand_chip.write_addr =s3c2440_write_addr;

         #endif

           nand_chip.read_data =s3c2440_read_data;

           nand_chip.nand_deselect_chip =s3c2440_nand_deselect_chip;

           

       

           //使能nand flash控制器

          //初始化ECC

          //禁止片选信号nFCE 

          s3c2440_nand->NFCONT =(1<<4) | (1<<1) | (1<<0);

          

          

          //设置时序

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

        }

        nand_chip.nand_reset(); //复位nand flash

     }

      void nand_read(unsigned char *buf, unsigned long start_addr, int size)//读数据

     {

        int i,j;

         //地址或长度对齐

         //NAND Flash 每次读操作是以page为单位的,一个page在此是2048byte(不同的NAND Flash的page大小不一定相同),

         //因为2047的二进制表示是11个1, 即11111111111, 一个数如果是2048的倍数,低11bit必须是0, 即 ****00000000000

         //所以把一个数跟2047按位与就可判断它是不是2048的倍数。

        #define LANGE_PAGE  

         if(strat_addr & (2048-1) || (size & (2048-1))) //大页--2048byte

           return;

        #else

           //512的倍数

         if(start_addr & (512-1) || (size & (512-1)) ) //小页--512byte

           return;

         #endif  

        

       //选中芯片

       nand_chip.nand_select_chip();

        

       对于小页而言,进行读取数据需要发命令00h/01h;

       对于大页而言,进行读取数据需要发命令00h ,30h;

       

       小页:

      

       

       

       大页:

       

       for(i=strat_addr;i<(start_addr + size);){

       //发出命令

       nand_chip.write_cmd(0); //00h

       

       //写地址

       nand_chip.write_addr(i);

      

      #ifdef LANGE_PAGE

        nand_chip.write_cmd(0x30);

      #endif

      //等待  

      nand.chip.nand_wait();

      #ifdef LANGE_PAGE

        for(j=0;j<2048;j++,i++){

      #else

        for(j=0;j<512;j++,i++){

      #endif

        //读数据

        *buf=nand_chip.read_data();

         buf++;

      }

     }

       //取消片选信号 

       nand_chip.nand_deselect_chip();

       return ;

     }

      (4)关看门狗和配置存储管理器

       init.c

       

       #define WHITCH_DOG  (*(volatile unsigned long*)0x53000000)

       #define MEM_BASE  0x48000000  //存储管理器寄存器的起始地址

       void disable_watch_dog(void)

       {

         WATCH_DOG = 0;

      

       }  

       void mem_setup(void)

      {

         int i=0;

         unsigned long *p=(unsigned long *)MEM_BASE;

         unsigned long const mem_cfg_val[]={

     

                          0x22011110,

                          0x00000700,

                          0x00000700,

                          0x00000700,

                          0x00000700,

                          0x00000700,

                          0x00000700,

                          0x00018005,

                          0x00018005,

                          0x008C07A3,

                          0x000000B1,

                          0x00000030,

                          0x00000030

          };

        for(i=0;i<13;i++)

         {

           p[i]=mem_cfg_val[i];

         }

      }

      (5)crt.S

      .text

        .global _strat

        _strat:

           ldr sp,=4096

               bl disable_watch_dog

               bl mem_setup

               bl nand_init

        

               ldr r0,=0x30000000 @buf

               mov r1,#4096       @strat_addr

               mov r2,#2048       @size

               bl nand_read

               ldr sp,=0x34000000

               ldr pc,=main

    halt_loop:

               b halt_loop

      (6)Makefile 

      objs := crt.o nand.o init.o leds.o

      nand.bin :$(objs)

        arm-linux-ld -Tnand.dis -o nand_elf $^

            arm-linux-objcopy -O binary -S nand_elf $@

            arm-linux-objdump -D -m arm nand_elf > nand.dis

      %.o :%.c

        arm-linux-gcc -Wall -c -O2 -o $@ $<

      %.o :%.S

        arm-linux-gcc -Wall -c -O2 -o $@ $<

      clean:

        rm -f nand.dis nand.bin nand_elf *.o

       

       

  • 相关阅读:
    85. Maximal Rectangle
    120. Triangle
    72. Edit Distance
    39. Combination Sum
    44. Wildcard Matching
    138. Copy List with Random Pointer
    91. Decode Ways
    142. Linked List Cycle II
    异或的性质及应用
    64. Minimum Path Sum
  • 原文地址:https://www.cnblogs.com/darren-pty/p/darren_nand.html
Copyright © 2011-2022 走看看