移值2016的u-boot-第2篇-支持Nand flash启动
Posted 宁次
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了移值2016的u-boot-第2篇-支持Nand flash启动相关的知识,希望对你有一定的参考价值。
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,0\\n" 32 + "orr r0,r0,#0xc0000000\\n" 33 + "mcr p15,0,r0,c1,c0,0\\n" 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(; i<(addr + len);) 142 + { 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 215 @@ -82,11 +82,50 @@ 216 217 /* FCLK:HCLK:PCLK = 1:2:4 */ 218 /* default FCLK is 120 MHz ! */ 219 - ldr r0, =CLKDIVN 220 - mov r1, #3 221 - str r1, [r0] 222 + //ldr r0, =CLKDIVN 223 + //mov r1, #3 224 + //str r1, [r0] 225 + 226 + /* 设置分频参数 */ 227 + ldr r0, =CLKDIVN 228 + mov r1, #0x05; /* FCLK:HCLK:PCLK=1:4:8 */ 229 + str r1, [r0] 230 + 231 + /* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */ 232 + mrc p15, 0, r1, c1, c0, 0 /* 读出控制寄存器 */ 233 + orr r1, r1, #0xc0000000 /* 设置为“asynchronous bus mode” */ 234 + mcr p15, 0, r1, c1, c0, 0 /* 写入控制寄存器 */ 235 + 236 + /* 配置时钟 */ 237 + #define S3C2440_MPLL_400MHZ ((0x5c<<12)|(0x01<<4)|(0x01)) 238 + ldr r0, =0x4c000004 239 + ldr r1, =S3C2440_MPLL_400MHZ 240 + str r1, [r0] 241 + 242 #endif /* CONFIG_S3C24X0 */ 243 244 + /** 245 + * 调用 init.c 中的初始化 246 + * 因为已经初始化好内存 所以 sp 在 顶部 247 + * 在 NOR 时不能用片内 4K 248 + */ 249 + ldr sp, =4096 250 + bl init_sdram 251 + ldr sp, =0x34000000 252 + bl nand_init_ll 253 + /** 254 + * 从 0 地址开始复制 到 SDRAM 中 255 + * 在 smdk2440.h 中定义 #define CONFIG_SYS_TEXT_BASE 256 + * u-boot 的加载地址 257 + */ 258 + mov r0,#0 259 + ldr r1, =CONFIG_SYS_TEXT_BASE 260 + ldr r2, =__bss_start 261 + sub r2, r2, r1 262 + bl copy_code_to_sdram 263 + bl clear_bss 264 + ldr pc, =_main 265 + 266 /* 267 * we do sys-critical inits only at reboot, 268 * not when booting from ram! 269 @@ -95,8 +134,6 @@ 270 bl cpu_init_crit 271 #endif 272 273 - bl _main 274 - 275 /*------------------------------------------------------------------------------*/ 276 277 .globl c_runtime_cpu_setup 278 diff -urN u-boot-2016.03/arch/arm/cpu/u-boot.lds u-boot-2016.03-ok/arch/arm/cpu/u-boot.lds 279 --- u-boot-2016.03/arch/arm/cpu/u-boot.lds 2016-03-14 22:20:21.000000000 +0800 280 +++ u-boot-2016.03-ok/arch/arm/cpu/u-boot.lds 2016-05-12 09:28:12.338040880 +0800 281 @@ -32,7 +32,7 @@ 282 */ 283 /DISCARD/ : { *(.rel._secure*) } 284 #endif 285 - . = 0x00000000; 286 + . = 0; 287 288 . = ALIGN(4); 289 .text : 290 diff -urN u-boot-2016.03/arch/arm/Kconfig u-boot-2016.03-ok/arch/arm/Kconfig 291 --- u-boot-2016.03/arch/arm/Kconfig 2016-03-14 22:20:21.000000000 +0800 292 +++ u-boot-2016.03-ok/arch/arm/Kconfig 2016-05-09 08:48:52.118143749 +0800 293 @@ -91,6 +91,10 @@ 294 config TARGET_SMDK2410 295 bool "Support smdk2410" 296 select CPU_ARM920T 297 + 298 +config TARGET_SMDK2440 299 + bool "Support smdk2440" 300 + select CPU_ARM920T 301 302 config TARGET_ASPENITE 303 bool "Support aspenite" 304 @@ -829,6 +833,7 @@ 305 source "board/phytec/pcm052/Kconfig" 306 source "board/ppcag/bg0900/Kconfig" 307 source "board/samsung/smdk2410/Kconfig" 308 +source "board/samsung/smdk2440/Kconfig" 309 source "board/sandisk/sansa_fuze_plus/Kconfig" 310 source "board/schulercontrol/sc_sps_1/Kconfig" 311 source "board/siemens/draco/Kconfig" 312 diff -urN u-boot-2016.03/arch/arm/lib/crt0.S u-boot-2016.03-ok/arch/arm/lib/crt0.S 313 --- u-boot-2016.03/arch/arm/lib/crt0.S 2016-03-14 22:20:21.000000000 +0800 314 +++ u-boot-2016.03-ok/arch/arm/lib/crt0.S 2016-05-16 17:11:44.287690421 +0800 315 @@ -99,7 +99,6 @@ 316 * relocate_code(addr_moni). Trick here is that we\'ll return 317 * \'here\' but relocated. 318 */ 319 - 320 ldr sp, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */ 321 #if defined(CONFIG_CPU_V7M) /* v7M forbids using SP as BIC destination */ 322 mov r3, sp 323 @@ -130,14 +129,17 @@ 324 325 bl c_runtime_cpu_setup /* we still call old routine here */ 326 #endif 327 + 328 + 329 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FRAMEWORK) 330 -# ifdef CONFIG_SPL_BUILD 331 +#ifdef CONFIG_SPL_BUILD 332 /* Use a DRAM stack for the rest of SPL, if requested */ 333 bl spl_relocate_stack_gd 334 cmp r0, #0 335 movne sp, r0 336 movne r9, r0 337 -# endif 338 +#endif 339 + 340 ldr r0, =__bss_start /* this is auto-relocated! */ 341 342 #ifdef CONFIG_USE_ARCH_MEMSET 343 @@ -177,3 +179,4 @@ 344 #endif 345 346 ENDPROC(_main) 347 + 348 diff -urN u-boot-2016.03/arch/arm/lib/relocate.S u-boot-2016.03-ok/arch/arm/lib/relocate.S 349 --- u-boot-2016.03/arch/arm/lib/relocate.S 2016-03-14 22:20:21.000000000 +0800 350 +++ u-boot-2016.03-ok/arch/arm/lib/relocate.S 2016-05-16 17:11:48.481661370 +0800 351 @@ -26,6 +26,7 @@ 352 353 ENTRY(relocate_vectors) 354 355 + 356 #ifdef CONFIG_CPU_V7M 357 /* 358 * On ARMv7-M we only have to write the new vector address 359 diff -urN u-boot-2016.03/board/samsung/smdk2440/Kconfig u-boot-2016.03-ok/board/samsung/smdk2440/Kconfig 360 --- u-boot-2016.03/board/samsung/smdk2440/Kconfig以上是关于移值2016的u-boot-第2篇-支持Nand flash启动的主要内容,如果未能解决你的问题,请参考以下文章
s3c2440 移值u-boot-2016.03 第6篇 支持mtd yaffs 烧写
s3c2440 移值2016的u-boot-第3篇-支持Nor flash 识别
s3c2440 移值u-boot-2016.03 第5篇 支持dm9000 识别
u-boot2016.05 有关 4096page size , oob == 224 nand 的移植支持