标签:des style blog http io color ar 使用 sp
一。环境和编译器
开发板: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 DOG 13 bl memsetup @初始化SDRAM 14 bl nand_init @初始化NAND Flash 15 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_read 22 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, //BWSCON 21 0x00000700, //BANKCON0 22 0x00000700, //BANKCON1 23 0x00000700, //BANKCON2 24 0x00000700, //BANKCON3 25 0x00000700, //BANKCON4 26 0x00000700, //BANKCON5 27 0x00018005, //BANKCON6 28 0x00018005, //BANKCON7 29 0x008C07A3, //REFRESH 30 0x000000B1, //BANKSIZE 31 0x00000030, //MRSRB6 32 0x00000030, //MRSRB7 33 }; 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 0 184 #define TWRPH0 3 185 #define TWRPH1 0 186 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 = 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:%.S 12 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理论性的东西改天附上。
标签:des style blog http io color ar 使用 sp
原文地址:http://www.cnblogs.com/hulig7/p/4088187.html