1, 要求:在4K 的代码以内,完成 NOR NAND 类型判断,初始化 NAND 复制自身到 SDRAM ,重定向。
2, 在 /arch/arm/cpu/arm920t/ 文件夹里 添加一个 inic.c 的文件,要在这个文件里面做上面说的事情。
修改 /arch/arm/cpu/arm920t/Makefile 加入 inic.c 的 编译。
extra-y = start.o
obj-y += init.o
obj-y += cpu.o
init.c 最后有补丁文件
3, 在 start.S 中初始化 SP 后调用 init.c 中的 初始化 NAND FLASH 和 复制 u-boot 到 SDRAM 清BSS 等
ldr sp, =4096 #在 NOR 启动时定在这里是不能写的,sp 中通常是保存 入栈 出栈 , 局部变量等,因为函数中并没有用到,设不设这里都可以。
bl init_sdram
ldr sp, =0x34000000
bl nand_init_ll
/**
* 从 0 地址开始复制 到 SDRAM 中
* 在 smdk2440.h 中定义 #define CONFIG_SYS_TEXT_BASE
* u-boot 的加载地址
*/
mov r0,#0
ldr r1,=CONFIG_SYS_TEXT_BASE
ldr r2,=__bss_start
sub r2, r2, r1
bl copy_code_to_sdram
bl clear_bss #清不清都可以,因为重定向那里还要在清一次,为了以后去掉重定向这里也清。
#从片内 4K 跳到 SDRAM 中 bl 不行,要用 ldr pc
ldr pc,=_main
4, 启用流程
/arch/arm/cpu/arm920t/start.S
/arch/arm/lib/crt0.S
u-boot 第一阶段
/common/Board_f.c 中的 board_init_f() 函数
最后调用
jump_to_copy()
if (gd->flags & GD_FLG_SKIP_RELOC)
return 0;
调用/arch/arm/librelocate.S relocate_code(gd->start_addr_sp, gd->new_gd, gd->relocaddr);
执行完毕后返回
crt0.S
bl board_init_f
下面直接执行第2阶段,也是因为执行了重定位,bl 跳不了
ldr pc, =board_init_r
5, 如何兼容 NOR FLASH NAND FLASH 启用?
不改动 原来的 重定位代码比较简单。
兼容 NOR FLASH NAND FLASH 的方法是,如果不想修改重定位的代码,就是先把 u-boot 复制到
SDRAM 的一个低地址,然后,它会从 这里在复制到 SDRAM 的高地址去。
NAND FLASH 启用要做的就是,在 4K 自动复制的代码里面,实现把u-boot 复制到 SDRAM 的低地址
6, 确定一个可用的链接地址
crt0.S
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
这里先把 sp 定在了最低端,因此不能使用 0x30000000
又因为u-boot 最终会被放到高地址也不能用 0x34000000
因为内存很大,放在10M 的位置吧。
在 smdk2440.h 中定义 #define CONFIG_SYS_TEXT_BASE 0x30a00000
补丁文件:
1 diff -urN u-boot-2016.03/arch/arm/cpu/arm920t/init.c u-boot-2016.03-ok/arch/arm/cpu/arm920t/init.c
2 --- u-boot-2016.03/arch/arm/cpu/arm920t/init.c 1970-01-01 07:00:00.000000000 +0700
3 +++ u-boot-2016.03-ok/arch/arm/cpu/arm920t/init.c 2016-05-17 06:48:31.635438931 +0800
4 @@ -0,0 +1,196 @@
5 +/* NAND FLASH控制器 */
6 +#define NFCONF (*((volatile unsigned long *)0x4E000000))
7 +#define NFCONT (*((volatile unsigned long *)0x4E000004))
8 +#define NFCMMD (*((volatile unsigned char *)0x4E000008))
9 +#define NFADDR (*((volatile unsigned char *)0x4E00000C))
10 +#define NFDATA (*((volatile unsigned char *)0x4E000010))
11 +#define NFSTAT (*((volatile unsigned char *)0x4E000020))
12 +
13 +/* CLK */
14 +#define CLKDIVN (*(volatile unsigned long *)0x4C000014)
15 +#define MPLLCON (*(volatile unsigned long *)0x4C000004)
16 +
17 +/* SDRAM */
18 +#define BWSCON (*(volatile unsigned long *)0x48000000)
19 +#define BANKCON6 (*(volatile unsigned long *)0x4800001c)
20 +#define REFRESH (*(volatile unsigned long *)0x48000024)
21 +#define BANKSIZE (*(volatile unsigned long *)0x48000028)
22 +#define MRSRB6 (*(volatile unsigned long *)0x4800002c)
23 +
24 +void init_clock(void)
25 +{
26 + //Mpll = 400M
27 + MPLLCON = (0x5c<<12) | (1<<4) | 1;
28 + //FCLK 400M HCLK 100M PCLK 50M
29 + CLKDIVN = 2<<1 | 1<<0;
30 + __asm__(
31 + "mrc p15,0,r0,c1,c0,0n"
32 + "orr r0,r0,#0xc0000000n"
33 + "mcr p15,0,r0,c1,c0,0n"
34 + );
35 +}
36 +
37 +void init_sdram(void)
38 +{
39 + BWSCON = 1<<25;
40 + BANKCON6 = 1<<16 | 1<<15 | 1;
41 + REFRESH = (1<<23) + 1268;
42 + BANKSIZE = 1<<7 | 1<<4 | 1;
43 + MRSRB6 = 0x30;
44 +}
45 +
46 +void clear_bss(void)
47 +{
48 + extern int __bss_start, __bss_end;
49 + int *p = &__bss_start;
50 +
51 + for (; p < &__bss_end; p++)
52 + {
53 + *p = 0;
54 + }
55 +}
56 +
57 +static void nand_latency(void)
58 +{
59 + int i=100;
60 + while(i--);
61 +}
62 +
63 +static void nand_is_ready(void)
64 +{
65 + //bit 0 : 1 不忙了
66 + while(! (NFSTAT & 1));
67 +}
68 +
69 +static void nand_write_addr(unsigned int addr)
70 +{
71 + int col, page;
72 + col = addr % 2048;
73 + page = addr / 2048;
74 +
75 + NFADDR = col & 0xff; /* Column Address A0~A7 */
76 + nand_latency();
77 + NFADDR = (col >> 8) & 0x0f; /* Column Address A8~A11 */
78 + nand_latency();
79 + NFADDR = page & 0xff; /* Row Address A12~A19 */
80 + nand_latency();
81 + NFADDR = (page >> 8) & 0xff; /* Row Address A20~A27 */
82 + nand_latency();
83 + NFADDR = (page >> 16) & 0x03; /* Row Address A28~A29 */
84 + nand_latency();
85 +}
86 +
87 +static unsigned char nand_read_char(void)
88 +{
89 + //只保留8个bit
90 + return NFDATA & 0xff;
91 +}
92 +
93 +static void nand_cmd(unsigned char cmd)
94 +{
95 + NFCMMD = cmd;
96 + nand_latency();
97 +}
98 +
99 +static void nand_select_chip(void)
100 +{
101 + //1bit : 0 选中
102 + NFCONT &= ~(1<<1);
103 +}
104 +
105 +static void nand_deselect_chip(void)
106 +{
107 + //1bit : 1 选中
108 + NFCONT |= (1<<1);
109 +}
110 +
111 +static void nand_reset(void)
112 +{
113 + nand_select_chip();
114 + nand_cmd(0xff);
115 + nand_deselect_chip();
116 +}
117 +
118 +void nand_init_ll(void)
119 +{
120 + //TACLS 3.3v 时 12ns
121 + #define TACLS 0
122 + //12ns
123 + #define TWRPH0 1
124 + //5ns
125 + #define TWRPH1 0
126 + NFCONF = TACLS<<12 | TWRPH0<<8 | TWRPH1<<4;
127 + /* 4 ECC
128 + * 1 CE 先不选中,用的时候在选中
129 + * 0 启动 flash controller
130 + */
131 + NFCONT = 1<<4 | 1<<1 | 1;
132 + nand_reset();
133 +}
134 +
135 +static void nand_read(unsigned int addr, unsigned char *buf, int len)
136 +{
137 + //选中
138 + nand_select_chip();
139 + //j 地址可能不是从0对齐开始读的
140 + unsigned int i = addr,j = addr % 2048;
141 + for(; i142 + {
143 + //读命令
144 + nand_cmd(0x00);
145 + nand_is_ready();
146 +
147 + //发送地址
148 + nand_write_addr(i);
149 + nand_is_ready();
150 +
151 + //在次发出读命令
152 + nand_cmd(0x30);
153 + nand_is_ready();
154 + //读2K
155 + for(; j<2048; j++)
156 + {
157 + *buf = nand_read_char();
158 + buf++;
159 + i++;
160 + }
161 + j=0;
162 + nand_latency();
163 + }
164 + //取消选中
165 + nand_deselect_chip();
166 +}
167 +
168 +static int boot_is_nor()
169 +{
170 + //利用 NOR 不能写的特点判断
171 + volatile unsigned int *p = (volatile unsigned int *)0;
172 + unsigned int val;
173 + val = *p;
174 + *p = 0x12345678;
175 + if(0x12345678 == *p)
176 + {
177 + *p = val;
178 + return 0;
179 + }
180 + return 1;
181 +}
182 +
183 +//片内4K 的程序要复制到链接SDRAM中去
184 +void copy_code_to_sdram(unsigned char *src,unsigned char *dst,int len)
185 +{
186 + int i = 0;
187 + if(boot_is_nor())
188 + {
189 + while(i < len)
190 + {
191 + dst[i] = src[i];
192 + i++;
193 + }
194 + }
195 + else
196 + {
197 + nand_read((int)src, dst, len);
198 + }
199 +}
200 +
201 diff -urN u-boot-2016.03/arch/arm/cpu/arm920t/Makefile u-boot-2016.03-ok/arch/arm/cpu/arm920t/Makefile
202 --- u-boot-2016.03/arch/arm/cpu/arm920t/Makefile 2016-03-14 22:20:21.000000000 +0800
203 +++ u-boot-2016.03-ok/arch/arm/cpu/arm920t/Makefile 2016-05-17 06:48:31.767626866 +0800
204 @@ -8,6 +8,7 @@
205 extra-y = start.o
206
207 obj-y += cpu.o
208 +obj-y += init.o
209 obj-$(CONFIG_USE_IRQ) += interrupts.o
210
211 obj-$(CONFIG_EP93XX) += ep93xx/
212 diff -urN u-boot-2016.03/arch/arm/cpu/arm920t/start.S u-boot-2016.03-ok/arch/arm/cpu/arm920t/start.S
213 --- u-boot-2016.03/arch/arm/cpu/arm920t/start.S 2016-03-14 22:20:21.000000000 +0800
214 +++ u-boot-2016.03-ok/arch/arm/cpu/arm920t/start.S 2016-05-17 06:48:31.782641369 +0800