一。环境和编译器
开发板:jz2440
系统:ubuntu12.04
编译器:gcc
二。验证代码
1.head.S
1 @******************************************************************************
2 @ File:head.s
3 @ 功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行
4 @auther:
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处
20 mov r2, #2048 @3. 复制长度= 2048(bytes)
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 /*关掉看门狗 */
8 void disable_watch_dog()
9 {
10 WTCON = 0;
11 }
12
13 /* 设置SDRAM */
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 typedef struct {
11 S3C24X0_REG32 NFCONF;
12 S3C24X0_REG32 NFCONT;
13 S3C24X0_REG32 NFCMD;
14 S3C24X0_REG32 NFADDR;
15 S3C24X0_REG32 NFDATA;
16 S3C24X0_REG32 NFMECCD0;
17 S3C24X0_REG32 NFMECCD1;
18 S3C24X0_REG32 NFSECCD;
19 S3C24X0_REG32 NFSTAT;
20 S3C24X0_REG32 NFESTAT0;
21 S3C24X0_REG32 NFESTAT1;
22 S3C24X0_REG32 NFMECC0;
23 S3C24X0_REG32 NFMECC1;
24 S3C24X0_REG32 NFSECC;
25 S3C24X0_REG32 NFSBLK;
26 S3C24X0_REG32 NFEBLK;
27 } S3C2440_NAND;
28
29 static S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
30
31
32
33 /* 供外部调用的函数 */
34 void nand_init(void);
35 void nand_read(unsigned char *buf, unsigned long start_addr, int size);
36
37
38 /* S3C2440的NAND Flash处理函数 */
39 static void s3c2440_nand_reset(void);
40 static void s3c2440_wait_idle(void);
41 static void s3c2440_nand_select_chip(void);
42 static void s3c2440_nand_deselect_chip(void);
43 static void s3c2440_write_cmd(int cmd);
44 static void s3c2440_write_addr_lp(unsigned int addr);
45 static unsigned char s3c2440_read_data(void);
46
47
48
49 /* 复位 */
50 static void s3c2440_nand_reset(void)
51 {
52 s3c2440_nand_select_chip();
53 s3c2440_write_cmd(0xff); // 复位命令
54 s3c2440_wait_idle();
55 s3c2440_nand_deselect_chip();
56 }
57
58 /* 等待NAND Flash就绪 */
59 static void s3c2440_wait_idle(void)
60 {
61 int i;
62 volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFSTAT;
63 while(!(*p & BUSY))
64 for(i=0; i<10; i++);
65 }
66
67 /* 发出片选信号 */
68 static void s3c2440_nand_select_chip(void)
69 {
70 int i;
71 s3c2440nand->NFCONT &= ~(1<<1);
72 for(i=0; i<10; i++);
73 }
74
75 /* 取消片选信号 */
76 static void s3c2440_nand_deselect_chip(void)
77 {
78 s3c2440nand->NFCONT |= (1<<1);
79 }
80
81 /* 发出命令 */
82 static void s3c2440_write_cmd(int cmd)
83 {
84 volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFCMD;
85 *p = cmd;
86 }
87
88
89
90
91 static void s3c2440_write_addr_lp(unsigned int addr)
92 {
93 int i;
94 volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR;
95 int col, page;
96
97 col = addr & NAND_BLOCK_MASK_LP;