* * copy U-Boot to SDRAM and jump to ram (from NAND or OneNAND) * r0: size to be compared * Load 1'st 2blocks to RAM because U-boot's size is larger than 1block(128k) size */////////////////////////////////////////////////////////////////////////////////////////////////////////////////// .globl copy_from_nand copy_from_nand: mov r10, lr /* save return address */ mov r9, r0 /* get ready to call C functions */ ldr sp, _TEXT_PHY_BASE /* setup temp stack pointer */ sub sp, sp, #12 mov fp, #0 /* no previous frame, so fp=0 */ mov r9, #0x1000 bl copy_uboot_to_ram /* 此函数需要添加,稍后说明。 */ 3: tst r0, #0x0 bne copy_failed /* 判断返回值是否失败 */ ldr r0, =0x0c000000 /* 判断内容是否一致 */ ldr r1, _TEXT_PHY_BASE 1: ldr r3, [r0], #4 ldr r4, [r1], #4 teq r3, r4 bne compare_failed /* not matched */ subs r9, r9, #4 bne 1b 4: mov lr, r10 /* all is OK */ mov pc, lr copy_failed: nop /* copy from nand failed */ b copy_failed compare_failed: nop /* compare failed */ b compare_failed
<Ps:这个错误由以为网友提出,在此表示感谢....希望更多的网友能够支持.谢谢>
这个文件比较大,分析篇我会重点分析,究竟nand是如何搬移数据的.这里我们只要复制下好了...
#include <common.h> #ifdef CONFIG_S3C64XX #include <asm/io.h> #include <linux/mtd/nand.h> #include <asm/arch/s3c6400.h> static int nandll_read_page(uchar * buf, ulong addr, int large_block) { int i; int page_size = 512; if (large_block == 1) page_size = 2048; if (large_block == 2) page_size = 4096; NAND_ENABLE_CE(); NFCMD_REG = NAND_CMD_READ0; /* Write Address */ NFADDR_REG = 0; if (large_block) NFADDR_REG = 0; NFADDR_REG = (addr) & 0xff; NFADDR_REG = (addr >> 8) & 0xff; NFADDR_REG = (addr >> 16) & 0xff; if (large_block) NFCMD_REG = NAND_CMD_READSTART; NF_TRANSRnB(); /* for compatibility(2460). u32 cannot be used. by scsuh */ for (i = 0; i < page_size; i++) { *buf++ = NFDATA8_REG; } NAND_DISABLE_CE(); return 0; } static int nandll_read_blocks(ulong dst_addr, ulong size, int large_block) { uchar *buf = (uchar *) dst_addr; int i; uint page_shift = 9; if (large_block == 1) page_shift = 11; /* Read pages */ if (large_block == 2) page_shift = 12; if (large_block == 2) { /* Read pages */ for (i = 0; i < 4; i++, buf += (1 << (page_shift - 1))) { nandll_read_page(buf, i, large_block); } /* Read pages */ for (i = 4; i < (0x60000 >> page_shift);i++, buf += (1 << page_shift)) { nandll_read_page(buf, i, large_block); } } else { for (i = 0; i < (0x60000 >> page_shift);i++, buf += (1 << page_shift)) { nandll_read_page(buf, i, large_block); } } return 0; } int copy_uboot_to_ram(void) { int large_block = 0; int i; vu_char id; NAND_ENABLE_CE(); NFCMD_REG = NAND_CMD_READID; NFADDR_REG = 0x00; /* wait for a while */ for (i = 0; i < 200; i++) ; id = NFDATA8_REG; id = NFDATA8_REG; if (id > 0x80) large_block = 1; if (id == 0xd5) large_block = 2; /* read NAND Block. * 128KB ->240KB because of U-Boot size increase. by scsuh * So, read 0x3c000 bytes not 0x20000(128KB). */ return nandll_read_blocks(CONFIG_SYS_PHY_UBOOT_BASE, 0x60000,large_block); } #endif然后修改 Makefile 把我们的 nand_cp.c添加到 uboot中去编译
继续修改此篇:
到此眼看就已经结束了...好了,make吧....啥有一个错误,天哪....
arm-linux-gcc -E -g -Os -fno-common -ffixed-r8 -msoft-float -fno-common -ffixed-r8 -msoft-float -D__KERNEL__ -DTEXT_BASE=0 -I/media/LvApp/u-boot-2010.03/include -fno-builtin -ffreestanding -nostdinc -isystem /usr/local/arm/4.4.1/bin/../lib/gcc/arm-none-linux-gnueabi/4.4.1/include -pipe -DCONFIG_ARM -D__ARM__ -marm -mabi=aapcs-linux -mno-thumb-interwork -march=armv5t -march=armv5t -ansi -D__ASSEMBLY__ -P - </media/LvApp/u-boot-2010.03/nand_spl/board/samsung/smdk6410/u-boot.lds >/media/LvApp/u-boot-2010.03/nand_spl/u-boot.lds cd /media/LvApp/u-boot-2010.03/nand_spl/board/samsung/smdk6410 && arm-linux-ld -Bstatic -T /media/LvApp/u-boot-2010.03/nand_spl/u-boot.lds -Ttext 0 start.o cpu_init.o lowlevel_init.o nand_boot.o nand_ecc.o s3c64xx.o \ -Map /media/LvApp/u-boot-2010.03/nand_spl/u-boot-spl.map \ -o /media/LvApp/u-boot-2010.03/nand_spl/u-boot-spl start.o: In function `copy_from_nand': /media/LvApp/u-boot-2010.03/nand_spl/board/samsung/smdk6410/start.S:302: undefined reference to `copy_uboot_to_ram' make[1]: *** [/media/LvApp/u-boot-2010.03/nand_spl/u-boot-spl] Error 1 make[1]: Leaving directory `/media/LvApp/u-boot-2010.03/nand_spl/board/samsung/smdk6410' make: *** [nand_spl] Error 2别急别急,,,小错而已..是吧....我们仔细查看,这是一个链接错误,为嘛会链接出错了..在此看到有这一行
start.o cpu_init.o lowlevel_init.o nand_boot.o nand_ecc.o s3c64xx.o
看到这一行,内心就暗自偷笑下吧..找到问题所在了...为啥?copy_uboot_to_ram这个函数不就是在start.o中内调用的嘛...所以这里没有nand_cp.o被链接进来,铁定
链接错误的...那要怎么改..直接定位到这个错误的目录下u-boot-2010.03/nand_spl/board/samsung/smdk6410修改该目录下Makefile 添加如下所示:
COBJS = nand_boot.o nand_ecc.o s3c64xx.o nand_cp.o 后面得加上nand_cp.o
接着我们得模仿后面的写法,为nand_cp.o添加目标生成方法
# from SoC directory $(obj)cpu_init.S: @rm -f $@ @ln -s $(TOPDIR)/cpu/arm1176/s3c64xx/cpu_init.S $@ $(obj)nand_cp.c: @rm -f $@ @ln -s $(TOPDIR)/cpu/arm1176/nand_cp.c $@
难不成这就行了???你下载进去试试不就知道了...
不行?运行不了?为什么呢....首先我们分析下,启动的过程...arm上电之后开始0地址指令..0地址的指令(此处假设时钟是nand启动,,这里就是讨论这个问题)是由arm自主加载的..从nand
的前8k,那么前8K的代码也就是0---0x2000 的这一段了..在start.S 这个文件,我们都知道是第一条指令的位置,那么这个文件就必须要被拷贝到0地址对应起来咯...这样才能被正常执行.
这些是不是都同意呢?不同意....咱们私下讨论.联系我...同意的,咱们继续.往下分析
既然知道了start.s为开始的地方,那么这里面也是第一部分的引导代码,而大家都知道第一部分的代码其实不全的,,,启动部分只有一下部分被arm搬移,剩余的大部分其实还在nand中..
那么既然不全,也就是跳转啊,函数调用啊...都必须在0---0x2000 的位置内才能到访问到.而且还不能是跟符号相关的跳转.因为符号跳转是根据链接地址跳转的..链接地址大家应该都知道
是被链接到一个很高的内存地址处去了...0x5e000啥的那个地址...
继续啊...不能符号跳转,就必须是相对跳转了...只要保证第一部分中所有的函数调用,符号跳转都在0---0x2000中,那就没问题,正常执行....为此,我们看一下u-boot.map这个文件.发现一个问题
Linker script and memory map 0x00000000 . = 0x0 0x00000000 . = ALIGN (0x4) .text 0x57e00000 0x262a4 cpu/arm1176/start.o(.text) .text 0x57e00000 0x440 cpu/arm1176/start.o 0x57e00000 _start 0x57e00040 _end_vect 0x57e00048 _armboot_start 0x57e0004c _bss_start 0x57e00050 _bss_end 0x57e0010c copy_from_nand cpu/arm1176/s3c64xx/cpu_init.o(.text) .text 0x57e00440 0x124 cpu/arm1176/s3c64xx/cpu_init.o 0x57e00440 mem_ctrl_asm_init我们只看一小部分了....在这里我们看到_start符号地址正好是那个指定的链接地址..也就是代码的起始符号...地址很高..无所谓啦...我们看看start.S中都有哪些符号的调用吧..这里直接看这个符号吧
.text 0x57e1c268 0x1fc board/samsung/smdk6410/libsmdk6410.a(lowlevel_init.o) 0x57e1c26c lowlevel_init这个符号其实在strat.S中是要使用的,,那么在仔细一看这个地址挺高的,,,好像不在前8k中是吧...那么在执行的时候就找不到这个符号的代码了...
问题就是在这,,得确保第一部分需要用到的代码能被arm加载进前8k就好了....那就得需要告诉连接器,,你...就你..帮我把这个链接到前面去.别放后面...不然打你...
链接器就会帮你乖乖的链接上去了...至于链接怎么听话,那就得使用链接听得懂的话了...链接脚本....使用哪个链接脚本..自己看我前面的分析文档吧....
cpu/arm1176/u-boot.lds SECTIONS { . = 0x00000000; . = ALIGN(4); .text : { cpu/arm1176/start.o (.text) board/samsung/smdk6410/lowlevel_init.o (.text) cpu/arm1176/s3c64xx/cpu_init.o (.text) cpu/arm1176/nand_cp.o (.text) *(.text) } 只列出了被修改的部分...
board/samsung/smdk6410/u-boot-nand.lds SECTIONS { . = 0x00000000; . = ALIGN(4); .text : { cpu/arm1176/start.o (.text) cpu/arm1176/s3c64xx/cpu_init.o (.text) board/samsung/smdk6410/lowlevel_init.o (.text) cpu/arm1176/nand_cp.o (.text) *(.text) }
Linker script and memory map 0x00000000 . = 0x0 0x00000000 . = ALIGN (0x4) .text 0x57e00000 0x262a4 cpu/arm1176/start.o(.text) .text 0x57e00000 0x440 cpu/arm1176/start.o 0x57e00000 _start 0x57e00040 _end_vect 0x57e00048 _armboot_start 0x57e0004c _bss_start 0x57e00050 _bss_end 0x57e0010c copy_from_nand cpu/arm1176/s3c64xx/cpu_init.o(.text) .text 0x57e00440 0x124 cpu/arm1176/s3c64xx/cpu_init.o 0x57e00440 mem_ctrl_asm_init board/samsung/smdk6410/lowlevel_init.o(.text) .text 0x57e00564 0x1fc board/samsung/smdk6410/lowlevel_init.o 0x57e00568 lowlevel_init cpu/arm1176/nand_cp.o(.text) .text 0x57e00760 0x1b4 cpu/arm1176/nand_cp.o 0x57e00814 copy_uboot_to_ram