二、【s3c2440移植u-boot-2016-11】 支持Nand Flash启动u-boot

时间:2022-07-28 18:49:50

(一)Nand Flash上启动u-boot

在第一个博客NOR Flash上启动u-boot的u-boot.bin是不支持用Nand Flash启动,至于为什么呢?
我这里就不啰嗦了,直接进入我们的正题,想知道有兴趣的朋友可以百度一下。

1、增加board/samsung/smdk2440/init.c文件

diff -urN u-boot-2016.11/board/samsung/smdk2440/init.c u-boot-2016.11_s3c2440/board/samsung/smdk2440/init.c  
--- u-boot-2016.11/board/samsung/smdk2440/init.c 1970-01-01 08:00:00.000000000 +0800 
+++ u-boot-2016.11_s3c2440/board/samsung/smdk2440/init.c 2018-06-15 15:29:34.456161999 +0800 
@@ -0,0 +1,142 @@  
+ 
+/* NAND FLASH控制器 */ 
+#define NFCONF (*((volatile unsigned long *)0x4E000000)) 
+#define NFCONT (*((volatile unsigned long *)0x4E000004)) 
+#define NFCMMD (*((volatile unsigned char *)0x4E000008)) 
+#define NFADDR (*((volatile unsigned char *)0x4E00000C)) 
+#define NFDATA (*((volatile unsigned char *)0x4E000010)) 
+#define NFSTAT (*((volatile unsigned char *)0x4E000020)) 
+/* GPIO */ 
+#define GPHCON (*(volatile unsigned long *)0x56000070) 
+#define GPHUP (*(volatile unsigned long *)0x56000078) 
+/* UART registers*/ 
+#define ULCON0 (*(volatile unsigned long *)0x50000000) 
+#define UCON0 (*(volatile unsigned long *)0x50000004) 
+#define UFCON0 (*(volatile unsigned long *)0x50000008) 
+#define UMCON0 (*(volatile unsigned long *)0x5000000c) 
+#define UTRSTAT0 (*(volatile unsigned long *)0x50000010) 
+#define UTXH0 (*(volatile unsigned char *)0x50000020) 
+#define URXH0 (*(volatile unsigned char *)0x50000024) 
+#define UBRDIV0 (*(volatile unsigned long *)0x50000028) 
+#define TXD0READY (1<<2) 
+void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len); 
+static int isBootFromNorFlash(void) 
+{ 
+ volatile int *p = (volatile int *)0; 
+ int val; 
+ val = *p; 
+ *p = 0x12345678; 
+ if (*p == 0x12345678) 
+ { 
+ /* 写成功, 是nand启动 */ 
+ *p = val; 
+ return 0; 
+ } 
+ else 
+ { 
+ /* NOR不能像内存一样写 */ 
+ return 1; 
+ } 
+} 
+void copy_code_to_sdram(unsigned char *src, unsigned char *dest, unsigned int len) 
+{ 
+ int i = 0; 
+ /* 如果是NOR启动 */ 
+ if (isBootFromNorFlash()) 
+ { 
+ while (i < len) 
+ { 
+ dest[i] = src[i]; 
+ i++; 
+ } 
+ } 
+ else 
+ { 
+ //nand_init(); 
+ nand_read_ll((unsigned int)src, dest, len); 
+ } 
+} 
+void clear_bss(void) 
+{ 
+ extern int __bss_start, __bss_end; 
+ int *p = &__bss_start; 
+ for (; p < &__bss_end; p++) 
+ *p = 0; 
+} 
+void nand_init_ll(void) 
+{ 
+#define TACLS 0 
+#define TWRPH0 1 
+#define TWRPH1 0 
+ /* 设置时序 */ 
+ NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4); 
+ /* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */ 
+ NFCONT = (1<<4)|(1<<1)|(1<<0); 
+} 
+static void nand_select(void) 
+{ 
+ NFCONT &= ~(1<<1); 
+} 
+static void nand_deselect(void) 
+{ 
+ NFCONT |= (1<<1); 
+} 
+static void nand_cmd(unsigned char cmd) 
+{ 
+ volatile int i; 
+ NFCMMD = cmd; 
+ for (i = 0; i < 10; i++); 
+} 
+static void nand_addr(unsigned int addr) 
+{ 
+ unsigned int col = addr % 2048; 
+ unsigned int page = addr / 2048; 
+ volatile int i; 
+ NFADDR = col & 0xff; 
+ for (i = 0; i < 10; i++); 
+ NFADDR = (col >> 8) & 0xff; 
+ for (i = 0; i < 10; i++); 
+ NFADDR = page & 0xff; 
+ for (i = 0; i < 10; i++); 
+ NFADDR = (page >> 8) & 0xff; 
+ for (i = 0; i < 10; i++); 
+ NFADDR = (page >> 16) & 0xff; 
+ for (i = 0; i < 10; i++); 
+} 
+static void nand_wait_ready(void) 
+{ 
+ while (!(NFSTAT & 1)); 
+} 
+static unsigned char nand_data(void) 
+{ 
+ return NFDATA; 
+} 
+void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len) 
+{ 
+ int col = addr % 2048; 
+ int i = 0; 
+ /* 1. 选中 */ 
+ nand_select(); 
+ while (i < len) 
+ { 
+ /* 2. 发出读命令00h */ 
+ nand_cmd(0x00); 
+ /* 3. 发出地址(分5步发出) */ 
+ nand_addr(addr); 
+ /* 4. 发出读命令30h */ 
+ nand_cmd(0x30); 
+ /* 5. 判断状态 */ 
+ nand_wait_ready(); 
+ /* 6. 读数据 */ 
+ for (; (col < 2048) && (i < len); col++) 
+ { 
+ buf[i] = nand_data(); 
+ i++; 
+ addr++; 
+ } 
+ col = 0; 
+ } 
+ /* 7. 取消选中 */ 
+ nand_deselect(); 
+} 
+ 

2、修改arch/arm/lib/crt0.S

diff -urN u-boot-2016.11/arch/arm/lib/crt0.S u-boot-2016.11_s3c2440/arch/arm/lib/crt0.S
--- u-boot-2016.11/arch/arm/lib/crt0.S 2016-11-15 00:27:11.000000000 +0800
+++ u-boot-2016.11_s3c2440/arch/arm/lib/crt0.S 2018-06-15 15:30:16.773310005 +0800
@@ -82,15 +82,27 @@
 #else
    bic sp, sp, #7  /* 8-byte alignment for ABI compliance */
 #endif
- mov r0, sp
- bl board_init_f_alloc_reserve
- mov sp, r0
+ bl nand_init_ll
+ mov r0, #0
+ ldr r1, =_start
+ ldr r2, =__bss_start
+ sub r2, r2, r1
+ ldr r1, =CONFIG_SYS_TEXT_BASE
+ bl copy_code_to_sdram
+ bl clear_bss
+ ldr pc, =START_ON_RAM //start run on RAM
+
+START_ON_RAM:
+ mov r0, sp
+ bl board_init_f_alloc_reserve
+ mov sp, r0
    /* set up gd here, outside any C code */
- mov r9, r0
- bl board_init_f_init_reserve
+ mov r9, r0
+ bl board_init_f_init_reserve

- mov r0, #0
- bl board_init_f
+ mov r0, #0
+ bl board_init_f
+ str r1, [r0]

 #if ! defined(CONFIG_SPL_BUILD)

@@ -118,17 +130,19 @@
    orr lr, #1              /* As required by Thumb-only */
 #endif
    ldr r0, [r9, #GD_RELOCADDR]     /* r0 = gd->relocaddr */
- b relocate_code
+ //b relocate_code
+ ldr r2, =__rel_dyn_start
+ ldr r3, =__rel_dyn_end
 here:
 /*
  * now relocate vectors
  */

- bl relocate_vectors
+ //bl relocate_vectors

 /* Set up final (full) environment */

- bl c_runtime_cpu_setup /* we still call old routine here */
+ //bl c_runtime_cpu_setup /* we still call old routine here */
 #endif
 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FRAMEWORK)
 # ifdef CONFIG_SPL_BUILD
@@ -138,6 +152,8 @@
    movne   sp, r0
    movne   r9, r0
 # endif
+
+#if 0
    ldr r0, =__bss_start    /* this is auto-relocated! */

 #ifdef CONFIG_USE_ARCH_MEMSET
@@ -158,6 +174,7 @@
    addlo   r0, r0, #4      /* move to next */
    blo clbss_l
 #endif
+#endif

 #if ! defined(CONFIG_SPL_BUILD)
    bl coloured_LED_init

3、修改include/configs/smdk2440.h

diff -urN u-boot-2016.11/include/configs/smdk2440.h u-boot-2016.11_s3c2440/include/configs/smdk2440.h
--- u-boot-2016.11/include/configs/smdk2440.h 2018-06-15 00:00:40.163660155 +0800
+++ u-boot-2016.11_s3c2440/include/configs/smdk2440.h 2018-06-15 15:34:23.276500000 +0800
@@ -21,7 +21,7 @@
 #define CONFIG_S3C2440     /* specifically a SAMSUNG S3C2440 SoC */
 #define CONFIG_SMDK2440        /* on a SAMSUNG SMDK2440 Board */

-#define CONFIG_SYS_TEXT_BASE 0x0
+#define CONFIG_SYS_TEXT_BASE 0x33f00000

 #define CONFIG_SYS_ARM_CACHE_WRITETHROUGH

4、修改board/samsung/smdk2440/Makefile将我们之前增加的init.c编译进来

diff -urN u-boot-2016.11/board/samsung/smdk2440/Makefile u-boot-2016.11_s3c2440/board/samsung/smdk2440/Makefile
--- u-boot-2016.11/board/samsung/smdk2440/Makefile 2018-06-14 22:37:01.047660155 +0800
+++ u-boot-2016.11_s3c2440/board/samsung/smdk2440/Makefile 2018-06-15 15:31:48.571186000 +0800
@@ -7,3 +7,4 @@

 obj-y  := smdk2440.o
 obj-y  += lowlevel_init.o
+obj-y += init.o

5、arch/arm/lib/Makefile,将crt0.c和vectors.c单独编译,不要链接到built-in.o

diff -urN u-boot-2016.11/arch/arm/lib/Makefile u-boot-2016.11_s3c2440/arch/arm/lib/Makefile
--- u-boot-2016.11/arch/arm/lib/Makefile 2016-11-15 00:27:11.000000000 +0800
+++ u-boot-2016.11_s3c2440/arch/arm/lib/Makefile 2018-06-15 15:33:21.169461998 +0800
@@ -14,7 +14,8 @@
 else ifdef CONFIG_ARM64
 obj-y  += crt0_64.o
 else
-obj-y += vectors.o crt0.o
+#obj-y += vectors.o crt0.o
+extra-y += vectors.o crt0.o
 endif

 ifndef CONFIG_SPL_BUILD

6、修改arch/arm/cpu/u-boot.lds,保证代码拷贝函数在4K之前

diff -urN u-boot-2016.11/arch/arm/cpu/u-boot.lds u-boot-2016.11_s3c2440/arch/arm/cpu/u-boot.lds
--- u-boot-2016.11/arch/arm/cpu/u-boot.lds 2016-11-15 00:27:11.000000000 +0800
+++ u-boot-2016.11_s3c2440/arch/arm/cpu/u-boot.lds 2018-06-15 15:36:11.246458000 +0800
@@ -44,6 +44,9 @@
        *(.__image_copy_start)
        *(.vectors)
        CPUDIR/start.o (.text*)
+ arch/arm/lib/crt0.o (.text*)
+ arch/arm/lib/vectors.o (.text*)
+ board/samsung/smdk2440/built-in.o (.text*)
        *(.text*)
    }

7、分析反汇编文件看nand的初始化和代码的拷贝函数是否小于4kB

book@ubuntu:~/u-boot-2016.11$ ./auto_run.sh  
book@ubuntu:~/u-boot-2016.11$ arm-linux-objdump -D u-boot > u-boot.dis  
book@ubuntu:~/u-boot-2016.11$ gedit u-boot.dis
查找nand_init_ll可以看到text段的地址为33f00650~33f00664  
...  
33f00650 <nand_init_ll>:  
33f00650:<span style="white-space:pre;">    </span>e3a0344e <span style="white-space:pre;"> </span>mov<span style="white-space:pre;">   </span>r3, #1308622848<span style="white-space:pre;">   </span>; 0x4e000000  
33f00654:<span style="white-space:pre;">    </span>e3a02c01 <span style="white-space:pre;"> </span>mov<span style="white-space:pre;">   </span>r2, #256<span style="white-space:pre;">  </span>; 0x100  
33f00658:<span style="white-space:pre;">    </span>e5832000 <span style="white-space:pre;"> </span>str<span style="white-space:pre;">   </span>r2, [r3]  
33f0065c:<span style="white-space:pre;">    </span>e3a02013 <span style="white-space:pre;"> </span>mov<span style="white-space:pre;">   </span>r2, #19<span style="white-space:pre;">   </span>; 0x13  
33f00660:<span style="white-space:pre;">    </span>e5832004 <span style="white-space:pre;"> </span>str<span style="white-space:pre;">   </span>r2, [r3, #4]  
33f00664:<span style="white-space:pre;">    </span>e12fff1e <span style="white-space:pre;"> </span>bx<span style="white-space:pre;">    </span>lr  
...  

继续查找copy_code_to_sdram可以看到text段大的地址为33f00840~33f00894  
...  
33f00840 <copy_code_to_sdram>:  
33f00840:<span style="white-space:pre;">    </span>e59fc04c <span style="white-space:pre;"> </span>ldr<span style="white-space:pre;">   </span>ip, [pc, #76]<span style="white-space:pre;"> </span>; 33f00894 <copy_code_to_sdram+0x54>  
33f00844:<span style="white-space:pre;">    </span>e92d40f0 <span style="white-space:pre;"> </span>push<span style="white-space:pre;">  </span>{r4, r5, r6, r7, lr}  
33f00848:<span style="white-space:pre;">    </span>e3a04000 <span style="white-space:pre;"> </span>mov<span style="white-space:pre;">   </span>r4, #0<span style="white-space:pre;">    </span>; 0x0  
33f0084c:<span style="white-space:pre;">    </span>e5945000 <span style="white-space:pre;"> </span>ldr<span style="white-space:pre;">   </span>r5, [r4]  
33f00850:<span style="white-space:pre;">    </span>e584c000 <span style="white-space:pre;"> </span>str<span style="white-space:pre;">   </span>ip, [r4]  
33f00854:<span style="white-space:pre;">    </span>e5943000 <span style="white-space:pre;"> </span>ldr<span style="white-space:pre;">   </span>r3, [r4]  
33f00858:<span style="white-space:pre;">    </span>e153000c <span style="white-space:pre;"> </span>cmp<span style="white-space:pre;">   </span>r3, ip  
33f0085c:<span style="white-space:pre;">    </span>e1a07000 <span style="white-space:pre;"> </span>mov<span style="white-space:pre;">   </span>r7, r0  
33f00860:<span style="white-space:pre;">    </span>e1a0c002 <span style="white-space:pre;"> </span>mov<span style="white-space:pre;">   </span>ip, r2  
33f00864:<span style="white-space:pre;">    </span>e1a06001 <span style="white-space:pre;"> </span>mov<span style="white-space:pre;">   </span>r6, r1  
33f00868:<span style="white-space:pre;">    </span>11a02004 <span style="white-space:pre;"> </span>movne<span style="white-space:pre;"> </span>r2, r4  
33f0086c:<span style="white-space:pre;">    </span>1a000005 <span style="white-space:pre;"> </span>bne<span style="white-space:pre;">   </span>33f00888 <copy_code_to_sdram+0x48>  
33f00870:<span style="white-space:pre;">    </span>e5845000 <span style="white-space:pre;"> </span>str<span style="white-space:pre;">   </span>r5, [r4]  
33f00874:<span style="white-space:pre;">    </span>e8bd40f0 <span style="white-space:pre;"> </span>pop<span style="white-space:pre;">   </span>{r4, r5, r6, r7, lr}  
33f00878:<span style="white-space:pre;">    </span>eaffff87 <span style="white-space:pre;"> </span>b<span style="white-space:pre;"> </span>33f0069c <nand_read_ll>  
33f0087c:<span style="white-space:pre;">    </span>e7d73002 <span style="white-space:pre;"> </span>ldrb<span style="white-space:pre;">  </span>r3, [r7, r2]  
33f00880:<span style="white-space:pre;">    </span>e7c63002 <span style="white-space:pre;"> </span>strb<span style="white-space:pre;">  </span>r3, [r6, r2]  
33f00884:<span style="white-space:pre;">    </span>e2822001 <span style="white-space:pre;"> </span>add<span style="white-space:pre;">   </span>r2, r2, #1<span style="white-space:pre;">    </span>; 0x1  
33f00888:<span style="white-space:pre;">    </span>e152000c <span style="white-space:pre;"> </span>cmp<span style="white-space:pre;">   </span>r2, ip  
33f0088c:<span style="white-space:pre;">    </span>3afffffa <span style="white-space:pre;"> </span>bcc<span style="white-space:pre;">   </span>33f0087c <copy_code_to_sdram+0x3c>  
33f00890:<span style="white-space:pre;">    </span>e8bd80f0 <span style="white-space:pre;"> </span>pop<span style="white-space:pre;">   </span>{r4, r5, r6, r7, pc}  
33f00894:<span style="white-space:pre;">    </span>12345678 <span style="white-space:pre;"> </span>.word<span style="white-space:pre;"> </span>0x12345678  
...  
我们拷贝代码的基地址为33f00000,所以33f00894-33f00000=894(16)=2196(10)<4096=4KB

8、烧写u-boot.bin到Nand Flash上并启动

book@ubuntu:~/u-boot-2016.11$ ./auto_run.sh  

二、【s3c2440移植u-boot-2016-11】 支持Nand Flash启动u-boot
到这里初步可以用Nand Flash启动u-boot了