本帖最后由 qisha 于 2014-3-18 10:50 编辑
希望帮到你
Ok6410 Uboot nand_spl 分析
1.这次分析是基于 uboot 2012.10 和 uboot 2013.01.01 的。
2.做这个分析主要是因为网上关于这方面资料比较少(反正我当时遇到困难) 。
3.文章主要参考宁静致远的《嵌入式 linux 学习手册》
4.初次移植 uboot 或正在移植 uboot 但没有输出信息的可以参考一下
一、uboot 的组成
我们知道新的 uboot 有两部分组成:nand_spl 目录下的 u-boot-spl-16k.bin 和顶层
目录下的 u-boot。第一部分由硬件自动拷贝到片内 sram 中运行,第二部分由第
一部分代码拷贝到 ram 中运行。
二.代码分析
在顶层 Makefile 中有这样一段代码
- nand_spl: $(TIMESTAMP_FILE) $(VERSION_FILE) depend
- $(MAKE) -C nand_spl/board/$(BOARDDIR) all
- $(obj)u-boot-nand.bin: nand_spl $(obj)u-boot.bin
- cat $(obj)nand_spl/u-boot-spl-16k.bin $(obj)u-boot.bin 》
- $(obj)u-boot-nand.bin
说明我们 nandflash 启动的 uboot 依赖于 nand_spl u-boot.bin 两个目标, 而 nand_spl
正是要进入 nand_spl/board/$(BOARDDIR),然后 make ,BOARDDIR 的值可以
查到:在顶层目录下 config.mk 中有
- ifdef VENDOR
- BOARDDIR = $(VENDOR)/$(BOARD)
- else
- BOARDDIR = $(BOARD)
- Endif
厂商为 samsung,板为 smdk6410,所以要进入”nand_spl/board/samsung/smdk6410 “make
打开该目录下的 Makefile
我们可以看到
SOBJS = start.o cpu_init.o lowlevel_init.o
COBJS = nand_boot.o nand_ecc.o s3c64xx.o smdk6410_nand_spl.o nand_base.o
对这几个文件编译连接等处理之后就得到我们要的 u-boot-spl-16k.bin, 而这几个文件哪
里来?其实都是从其他文件链接过来的(什么叫链接?不懂百度一下吧) ,我们
看到有熟悉的 start.S,lowlevel.S 等,这些文件在第二阶段的代码中要用到,但
是通过宏开关, 使编译过程不一样, 得到的代码也有不小差异, 下面就来进行具
体的分析
打开 start.S
在 bl lowlevel_init /* go setup pll,mux,memory */之前
与《嵌入式 linux 学习手册》中讲的是一样的,接下来
- call_board_init_f:
- ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
- bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
- ldr r0,=0x00000000
- bl board_init_f
这个 board_init_f 函数就不是 board.c 中的了,因为编译链接时,board.c 根本就没参与进来,
在这里这个函数是在 smdk6410_nand_spl.c 中,
- void board_init_f(unsigned long bootflag)
- {
- relocate_code(8*1024, NULL,CONFIG_SYS_TEXT_BASE);
- }
打开 config.mk
有:include $(TOPDIR)/board/$(BOARDDIR)/config.mk
打开/board/samsung/smdk6410/config.mk
有:
- ifndef CONFIG_NAND_SPL
- CONFIG_SYS_TEXT_BASE = $(RAM_TEXT) # RAM_TEXT=57e00000
- else
- CONFIG_SYS_TEXT_BASE = 0
- Endif
有没有定义 CONFIG_NAND_SPL 呢?
搜索时没有发现 define XX 的
但是在 nand_spl/board/samsung/smdk6410 的 Makefile 中有
AFLAGS += -DCONFIG_NAND_SPL
CFLAGS += -DCONFIG_NAND_SPL -ffunction-sections
Gcc 编译规则中有说
gcc 编译的时候提供了预定义功能,参数是-D, 通过 man gcc 可以了解更多:
-D name
Predefine name as a macro, with definition 1.
-D name=definition
Predefine name as a macro, with definition definition. The
contents of definition are tokenized and processed as if they appeared
during translation phase three in a #define directive. In particular,
the definition will be truncated by embedded new-line characters.
就是说加参数-D name 就相当于#define name
这样 CONFIG_SYS_TEXT_BASE = 0
接着又回到 start.S 的 relocate_code
R2 的值就是函数的第三个参数的值,即为 0,直接跳到 clear_bss
- .globl relocate_code
- relocate_code:
- mov r4, r0 /* save addr_sp */
- mov r5, r1 /* save addr of gd */
- mov r6, r2 /* save addr of destination */ //CONFIG_SYS_TEXT_BASE
- /* Set up the stack */
- stack_setup:
- mov sp, r4
- adr r0, _start
- cmp r0, r6
- moveq r9, #0
- beq clear_bss //执行到这里
- mov r1, r6
- ldr r3, _bss_start_ofs
- add r2, r0, r3
////////////////////////////////////////////我是无敌分界线///////////////////////////////////////////////////////////////////////
清完 bss 之后就跳到_nand_boot,拷贝第二阶段的代码到 ram,然后跳到 ram 中执行
三、启动无信息原因
我总结了下:
1、/nand_spl/board/samsung/smdk6410/config.mk
PAD_TO := $(shell expr $$[$(CONFIG_SYS_TEXT_BASE) + 8192])
8192(原版是 4096)就是 u-boot-spl-16k.bin 的大小,到时会从 8192 之后复制代码
到 ram 中执行,如果第一阶段代码太多,超过 4K,又没有修改成 8192(或则大
于第一阶段代码) ,则复制的代码不是开头不是第二阶段代码的开头
2.在 lowlevel.S 中有
- //#ifndef CONFIG_S3C6410
- ldr r1, [r0, #OTHERS_OFFSET]
- bic r1, r1, #0xC0
- orr r1, r1, #0x40
- str r1, [r0, #OTHERS_OFFSET]
- wait_for_async:
- ldr r1, [r0, #OTHERS_OFFSET]
- and r1, r1, #0xf00
- cmp r1, #0x0
- bne wait_for_async
- //#endif
要将//#ifndef CONFIG_S3C6410 注释掉,具体为什么?好像没有定义 CONFIG_S3C6410
本帖最后由 qisha 于 2014-3-18 10:50 编辑
希望帮到你
Ok6410 Uboot nand_spl 分析
1.这次分析是基于 uboot 2012.10 和 uboot 2013.01.01 的。
2.做这个分析主要是因为网上关于这方面资料比较少(反正我当时遇到困难) 。
3.文章主要参考宁静致远的《嵌入式 linux 学习手册》
4.初次移植 uboot 或正在移植 uboot 但没有输出信息的可以参考一下
一、uboot 的组成
我们知道新的 uboot 有两部分组成:nand_spl 目录下的 u-boot-spl-16k.bin 和顶层
目录下的 u-boot。第一部分由硬件自动拷贝到片内 sram 中运行,第二部分由第
一部分代码拷贝到 ram 中运行。
二.代码分析
在顶层 Makefile 中有这样一段代码
- nand_spl: $(TIMESTAMP_FILE) $(VERSION_FILE) depend
- $(MAKE) -C nand_spl/board/$(BOARDDIR) all
- $(obj)u-boot-nand.bin: nand_spl $(obj)u-boot.bin
- cat $(obj)nand_spl/u-boot-spl-16k.bin $(obj)u-boot.bin 》
- $(obj)u-boot-nand.bin
说明我们 nandflash 启动的 uboot 依赖于 nand_spl u-boot.bin 两个目标, 而 nand_spl
正是要进入 nand_spl/board/$(BOARDDIR),然后 make ,BOARDDIR 的值可以
查到:在顶层目录下 config.mk 中有
- ifdef VENDOR
- BOARDDIR = $(VENDOR)/$(BOARD)
- else
- BOARDDIR = $(BOARD)
- Endif
厂商为 samsung,板为 smdk6410,所以要进入”nand_spl/board/samsung/smdk6410 “make
打开该目录下的 Makefile
我们可以看到
SOBJS = start.o cpu_init.o lowlevel_init.o
COBJS = nand_boot.o nand_ecc.o s3c64xx.o smdk6410_nand_spl.o nand_base.o
对这几个文件编译连接等处理之后就得到我们要的 u-boot-spl-16k.bin, 而这几个文件哪
里来?其实都是从其他文件链接过来的(什么叫链接?不懂百度一下吧) ,我们
看到有熟悉的 start.S,lowlevel.S 等,这些文件在第二阶段的代码中要用到,但
是通过宏开关, 使编译过程不一样, 得到的代码也有不小差异, 下面就来进行具
体的分析
打开 start.S
在 bl lowlevel_init /* go setup pll,mux,memory */之前
与《嵌入式 linux 学习手册》中讲的是一样的,接下来
- call_board_init_f:
- ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
- bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
- ldr r0,=0x00000000
- bl board_init_f
这个 board_init_f 函数就不是 board.c 中的了,因为编译链接时,board.c 根本就没参与进来,
在这里这个函数是在 smdk6410_nand_spl.c 中,
- void board_init_f(unsigned long bootflag)
- {
- relocate_code(8*1024, NULL,CONFIG_SYS_TEXT_BASE);
- }
打开 config.mk
有:include $(TOPDIR)/board/$(BOARDDIR)/config.mk
打开/board/samsung/smdk6410/config.mk
有:
- ifndef CONFIG_NAND_SPL
- CONFIG_SYS_TEXT_BASE = $(RAM_TEXT) # RAM_TEXT=57e00000
- else
- CONFIG_SYS_TEXT_BASE = 0
- Endif
有没有定义 CONFIG_NAND_SPL 呢?
搜索时没有发现 define XX 的
但是在 nand_spl/board/samsung/smdk6410 的 Makefile 中有
AFLAGS += -DCONFIG_NAND_SPL
CFLAGS += -DCONFIG_NAND_SPL -ffunction-sections
Gcc 编译规则中有说
gcc 编译的时候提供了预定义功能,参数是-D, 通过 man gcc 可以了解更多:
-D name
Predefine name as a macro, with definition 1.
-D name=definition
Predefine name as a macro, with definition definition. The
contents of definition are tokenized and processed as if they appeared
during translation phase three in a #define directive. In particular,
the definition will be truncated by embedded new-line characters.
就是说加参数-D name 就相当于#define name
这样 CONFIG_SYS_TEXT_BASE = 0
接着又回到 start.S 的 relocate_code
R2 的值就是函数的第三个参数的值,即为 0,直接跳到 clear_bss
- .globl relocate_code
- relocate_code:
- mov r4, r0 /* save addr_sp */
- mov r5, r1 /* save addr of gd */
- mov r6, r2 /* save addr of destination */ //CONFIG_SYS_TEXT_BASE
- /* Set up the stack */
- stack_setup:
- mov sp, r4
- adr r0, _start
- cmp r0, r6
- moveq r9, #0
- beq clear_bss //执行到这里
- mov r1, r6
- ldr r3, _bss_start_ofs
- add r2, r0, r3
////////////////////////////////////////////我是无敌分界线///////////////////////////////////////////////////////////////////////
清完 bss 之后就跳到_nand_boot,拷贝第二阶段的代码到 ram,然后跳到 ram 中执行
三、启动无信息原因
我总结了下:
1、/nand_spl/board/samsung/smdk6410/config.mk
PAD_TO := $(shell expr $$[$(CONFIG_SYS_TEXT_BASE) + 8192])
8192(原版是 4096)就是 u-boot-spl-16k.bin 的大小,到时会从 8192 之后复制代码
到 ram 中执行,如果第一阶段代码太多,超过 4K,又没有修改成 8192(或则大
于第一阶段代码) ,则复制的代码不是开头不是第二阶段代码的开头
2.在 lowlevel.S 中有
- //#ifndef CONFIG_S3C6410
- ldr r1, [r0, #OTHERS_OFFSET]
- bic r1, r1, #0xC0
- orr r1, r1, #0x40
- str r1, [r0, #OTHERS_OFFSET]
- wait_for_async:
- ldr r1, [r0, #OTHERS_OFFSET]
- and r1, r1, #0xf00
- cmp r1, #0x0
- bne wait_for_async
- //#endif
要将//#ifndef CONFIG_S3C6410 注释掉,具体为什么?好像没有定义 CONFIG_S3C6410
举报