首页 > 代码库 > 实验四--nand flash的使用

实验四--nand flash的使用

一。环境和编译器

  开发板:jz2440

       系统:ubuntu12.04

       编译器:gcc

二。验证代码

1.head.S

 1 @****************************************************************************** 2 @ File:head.s 3 @ 功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行 4 @auther:hulig 5 @******************************************************************************        6    7 .text 8 .global _start 9 _start:10             @函数disable_watch_dog, memsetup, init_nand, nand_read_ll在init.c中定义11             ldr     sp, =4096               @设置堆栈 12             bl      disable_watch_dog       @关WATCH DOG13             bl      memsetup                @初始化SDRAM14             bl      nand_init               @初始化NAND Flash15 16                                             @将NAND Flash中地址4096开始的1024字节代码(main.c编译得到)复制到SDRAM中17                                             @nand_read_ll函数需要3个参数:18             ldr     r0,     =0x30000000     @1. 目标地址=0x30000000,这是SDRAM的起始地址19             mov     r1,     #4096           @2.  源地址   = 4096,连接的时候,main.c中的代码都存在NAND Flash地址4096开始处20             mov     r2,     #2048           @3.  复制长度= 2048(bytes),对于本实验的main.c,这是足够了21             bl      nand_read               @调用C函数nand_read22 23             ldr     sp, =0x34000000         @设置栈24             ldr     lr, =halt_loop          @设置返回地址25             ldr     pc, =main               @b指令和bl指令只能前后跳转32M的范围,所以这里使用向pc赋值的方法进行跳转26 halt_loop:27             b       halt_loop

 

2.init.c

 1 #define     WTCON    (*(volatile unsigned long *)0x53000000) 2 #define     MEM_CTL_BASE        0x48000000 3   4 void disable_watch_dog(); 5 void memsetup(); 6  7 /*上电后,WATCH DOG默认是开着的,要把它关掉 */ 8 void disable_watch_dog() 9 {10     WTCON    = 0;11 }12 13 /* 设置控制SDRAM的13个寄存器 */14 void memsetup()15 {16     int     i = 0;17     unsigned long *p = (unsigned long *)MEM_CTL_BASE;18 19     /* SDRAM 13个寄存器的值 */20     unsigned long  const    mem_cfg_val[]={ 0x22011110,     //BWSCON21                                             0x00000700,     //BANKCON022                                             0x00000700,     //BANKCON123                                             0x00000700,     //BANKCON224                                             0x00000700,     //BANKCON3  25                                             0x00000700,     //BANKCON426                                             0x00000700,     //BANKCON527                                             0x00018005,     //BANKCON628                                             0x00018005,     //BANKCON729                                             0x008C07A3,     //REFRESH30                                             0x000000B1,     //BANKSIZE31                                             0x00000030,     //MRSRB632                                             0x00000030,     //MRSRB733                                     };34 35     for(; i < 13; i++)36         p[i] = mem_cfg_val[i];37 }

3.nand.c  以下代码不支持2410 也不支持小页读写,是裁剪源码的结果。

  1 #define GSTATUS1        (*(volatile unsigned int *)0x560000B0)  2 #define BUSY            1  3   4 #define NAND_SECTOR_SIZE_LP    2048  5 #define NAND_BLOCK_MASK_LP     (NAND_SECTOR_SIZE_LP - 1)  6   7 typedef unsigned int S3C24X0_REG32;  8   9  10  11 /* NAND FLASH (see S3C2440 manual chapter 6, www.100ask.net) */ 12 typedef struct { 13     S3C24X0_REG32   NFCONF; 14     S3C24X0_REG32   NFCONT; 15     S3C24X0_REG32   NFCMD; 16     S3C24X0_REG32   NFADDR; 17     S3C24X0_REG32   NFDATA; 18     S3C24X0_REG32   NFMECCD0; 19     S3C24X0_REG32   NFMECCD1; 20     S3C24X0_REG32   NFSECCD; 21     S3C24X0_REG32   NFSTAT; 22     S3C24X0_REG32   NFESTAT0; 23     S3C24X0_REG32   NFESTAT1; 24     S3C24X0_REG32   NFMECC0; 25     S3C24X0_REG32   NFMECC1; 26     S3C24X0_REG32   NFSECC; 27     S3C24X0_REG32   NFSBLK; 28     S3C24X0_REG32   NFEBLK; 29 } S3C2440_NAND; 30  31  32 typedef struct { 33     void (*nand_reset)(void); 34     void (*wait_idle)(void); 35     void (*nand_select_chip)(void); 36     void (*nand_deselect_chip)(void); 37     void (*write_cmd)(int cmd); 38     void (*write_addr)(unsigned int addr); 39     unsigned char (*read_data)(void); 40 }t_nand_chip; 41  42 static S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000; 43  44 static t_nand_chip nand_chip; 45  46 /* 供外部调用的函数 */ 47 void nand_init(void); 48 void nand_read(unsigned char *buf, unsigned long start_addr, int size); 49  50 /* NAND Flash操作的总入口, 它们将调用S3C2410或S3C2440的相应函数 */ 51 static void nand_reset(void); 52 static void wait_idle(void); 53 static void nand_select_chip(void); 54 static void nand_deselect_chip(void); 55 static void write_cmd(int cmd); 56 static void write_addr(unsigned int addr); 57 static unsigned char read_data(void); 58  59 /* S3C2440的NAND Flash处理函数 */ 60 static void s3c2440_nand_reset(void); 61 static void s3c2440_wait_idle(void); 62 static void s3c2440_nand_select_chip(void); 63 static void s3c2440_nand_deselect_chip(void); 64 static void s3c2440_write_cmd(int cmd); 65 static void s3c2440_write_addr_lp(unsigned int addr); 66 static unsigned char s3c2440_read_data(void); 67  68  69  70 /* 复位 */ 71 static void s3c2440_nand_reset(void) 72 { 73     s3c2440_nand_select_chip(); 74     s3c2440_write_cmd(0xff);  // 复位命令 75     s3c2440_wait_idle(); 76     s3c2440_nand_deselect_chip(); 77 } 78  79 /* 等待NAND Flash就绪 */ 80 static void s3c2440_wait_idle(void) 81 { 82     int i; 83     volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFSTAT; 84     while(!(*p & BUSY)) 85         for(i=0; i<10; i++); 86 } 87  88 /* 发出片选信号 */ 89 static void s3c2440_nand_select_chip(void) 90 { 91     int i; 92     s3c2440nand->NFCONT &= ~(1<<1); 93     for(i=0; i<10; i++);     94 } 95  96 /* 取消片选信号 */ 97 static void s3c2440_nand_deselect_chip(void) 98 { 99     s3c2440nand->NFCONT |= (1<<1);100 }101 102 /* 发出命令 */103 static void s3c2440_write_cmd(int cmd)104 {105     volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFCMD;106     *p = cmd;107 } 111 112 static void s3c2440_write_addr_lp(unsigned int addr)113 {114     int i;115     volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR;116     int col, page;117 118     col = addr & NAND_BLOCK_MASK_LP;119     page = addr / NAND_SECTOR_SIZE_LP;120     121     *p = col & 0xff;            /* Column Address A0~A7 */122     for(i=0; i<10; i++);        123     *p = (col >> 8) & 0x0f;     /* Column Address A8~A11 */124     for(i=0; i<10; i++);125     *p = page & 0xff;            /* Row Address A12~A19 */126     for(i=0; i<10; i++);127     *p = (page >> 8) & 0xff;    /* Row Address A20~A27 */128     for(i=0; i<10; i++);129     *p = (page >> 16) & 0x03;    /* Row Address A28~A29 */130     for(i=0; i<10; i++);131 }132 133 134 /* 读取数据 */135 static unsigned char s3c2440_read_data(void)136 {137     volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFDATA;138     return *p;139 }140 141 142 /* 在第一次使用NAND Flash前,复位一下NAND Flash */143 static void nand_reset(void)144 {145     nand_chip.nand_reset();146 }147 148 static void wait_idle(void)149 {150     nand_chip.wait_idle();151 }152 153 static void nand_select_chip(void)154 {155     int i;156     nand_chip.nand_select_chip();157     for(i=0; i<10; i++);158 }159 160 static void nand_deselect_chip(void)161 {162     nand_chip.nand_deselect_chip();163 }164 165 static void write_cmd(int cmd)166 {167     nand_chip.write_cmd(cmd);168 }169 static void write_addr(unsigned int addr)170 {171     nand_chip.write_addr(addr);172 }173 174 static unsigned char read_data(void)175 {176     return nand_chip.read_data();177 }178 179 180 /* 初始化NAND Flash */181 void nand_init(void)182 {183 #define TACLS   0184 #define TWRPH0  3185 #define TWRPH1  0186 187    188  189         nand_chip.nand_reset         = s3c2440_nand_reset;190         nand_chip.wait_idle          = s3c2440_wait_idle;191         nand_chip.nand_select_chip   = s3c2440_nand_select_chip;192         nand_chip.nand_deselect_chip = s3c2440_nand_deselect_chip;193         nand_chip.write_cmd          = s3c2440_write_cmd;194 195         nand_chip.write_addr         = s3c2440_write_addr_lp;196 197         nand_chip.read_data          =http://www.mamicode.com/ s3c2440_read_data;198 199         /* 设置时序 */200         s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);201         /* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */202         s3c2440nand->NFCONT = (1<<4)|(1<<1)|(1<<0);203    204     205     /* 复位NAND Flash */206     nand_reset();207 }208 209 210 /* 读函数 */211 void nand_read(unsigned char *buf, unsigned long start_addr, int size)212 {213     int i, j;214 215 216     if ((start_addr & NAND_BLOCK_MASK_LP) || (size & NAND_BLOCK_MASK_LP)) {217         return ;    /* 地址或长度不对齐 */218     }                  219     //2047 =0b111_1111_1111   若start_addr低11位都是0,则说明对齐;否则不对齐,此时直接return
220 221 /* 选中芯片 */222 nand_select_chip();223 224 for(i=start_addr; i < (start_addr + size);) {225 /* 发出READ0命令 */226 write_cmd(0);227 228 /* Write Address */229 write_addr(i);230 231 write_cmd(0x30); 232 233 wait_idle();234 235 236 for(j=0; j < NAND_SECTOR_SIZE_LP; j++, i++) {237 238 *buf = read_data();239 buf++;240 }241 }242 243 /* 取消片选信号 */244 nand_deselect_chip();245 246 return ;247 }

4.led.c

    就是led闪烁之类的,免了。

5.Makefile

  

 1 objs := head.o init.o nand.o led.o 2  3 nand.bin : $(objs) 4     arm-linux-ld -Tnand.lds    -o nand_elf $^ 5     arm-linux-objcopy -O binary -S nand_elf $@ 6     arm-linux-objdump -D -m arm  nand_elf > nand.dis 7  8 %.o:%.c 9     arm-linux-gcc -Wall -c -O2 -o $@ $<10 11 %.o:%.S12     arm-linux-gcc -Wall -c -O2 -o $@ $<13 14 clean:15     rm -f  nand.dis nand.bin nand_elf  *.o

以上makefile与之前不同,下面是编译细节,请用心比较

6.链接脚本

1 SECTIONS { 2   firtst      0x00000000 : { head.o init.o nand.o}3   second     0x30000000 : AT(4096) { led.o }4 } 5  

 

三。实验结果

  经验证,可实现。

  本代码参考韦东山先生的源码,作来相应的裁剪。

  源码上支持2410和2440,以及大页,小页的读写,这里都分别作了裁剪到开发板可用的程度。

  上面代码很复杂的感觉,进一步简化  ,有时间再说。

  nand flash理论性的东西改天附上。

 

实验四--nand flash的使用