u-boot移植(十三)---代码修改---裁剪及环境变量 一
一、内核裁剪
内核的裁剪首先就是修改我们的配置文件,即 include/configs/jz2440.h 文件,里面定义的很多宏,我们也许用不上的就要去掉。
1 /*
2 * (C) Copyright 2002
3 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
4 * Marius Groeger <mgroeger@sysgo.de>
5 * Gary Jennejohn <garyj@denx.de>
6 * David Mueller <d.mueller@elsoft.ch>
7 *
8 * Configuation settings for the JZ2440 board.
9 *
10 * SPDX-License-Identifier: GPL-2.0+
11 */
12
13 #ifndef __CONFIG_H
14 #define __CONFIG_H
15
16 /*
17 * High Level Configuration Options
18 * (easy to change)
19 */
20 #define CONFIG_S3C24X0 /* This is a SAMSUNG S3C24x0-type SoC */
21 #define CONFIG_JZ2440 /* on a JZ2440 Board */
22 #define CONFIG_S3C2440
23
24 /* 内存为64M(34000000),34000000 - 33F00000 = 100000 即为1M*/
25 #define CONFIG_SYS_TEXT_BASE 0x33f00000
26
27 #define DEBUG
28
29 #define CONFIG_SYS_ARM_CACHE_WRITETHROUGH
30
31 /* input clock of PLL (the JZ2440 has 12MHz input clock) */
32 #define CONFIG_SYS_CLK_FREQ 12000000
33
34 #define CONFIG_CMDLINE_TAG /* enable passing of ATAGs */
35 #define CONFIG_SETUP_MEMORY_TAGS
36 #define CONFIG_INITRD_TAG
37
38 /*
39 * Hardware drivers
40 */
41 #if 0
42 #define CONFIG_CS8900 /* we have a CS8900 on-board */
43 #define CONFIG_CS8900_BASE 0x19000300
44 #define CONFIG_CS8900_BUS16 /* the Linux driver does accesses as shorts */
45 #else
46 #define CONFIG_DRIVER_DM9000
47 #endif
48
49 /*
50 * select serial console configuration
51 */
52 #define CONFIG_S3C24X0_SERIAL
53 #define CONFIG_SERIAL1 1 /* we use SERIAL 1 on JZ2440 */
54
55 /************************************************************
56 * USB support (currently only works with D-cache off)
57 ************************************************************/
58 #define CONFIG_USB_OHCI
59 #define CONFIG_USB_OHCI_S3C24XX
60 #define CONFIG_USB_KEYBOARD
61 #define CONFIG_USB_STORAGE
62 #define CONFIG_DOS_PARTITION
63
64 /************************************************************
65 * RTC
66 ************************************************************/
67 #define CONFIG_RTC_S3C24X0
68
69
70 #define CONFIG_BAUDRATE 115200
71
72 /*
73 * BOOTP options
74 */
75 #define CONFIG_BOOTP_BOOTFILESIZE
76 #define CONFIG_BOOTP_BOOTPATH
77 #define CONFIG_BOOTP_GATEWAY
78 #define CONFIG_BOOTP_HOSTNAME
79
80 /*
81 * Command line configuration.
82 */
83 #define CONFIG_CMD_BSP
84 #define CONFIG_CMD_CACHE
85 #define CONFIG_CMD_DATE
86 #define CONFIG_CMD_DHCP
87 #define CONFIG_CMD_NAND
88 #define CONFIG_CMD_PING
89 #define CONFIG_CMD_REGINFO
90 #define CONFIG_CMD_USB
91
92 #define CONFIG_SYS_HUSH_PARSER
93 #define CONFIG_CMDLINE_EDITING
94
95 /* autoboot */
96 #define CONFIG_BOOTDELAY 5
97 #define CONFIG_BOOT_RETRY_TIME -1
98 #define CONFIG_RESET_TO_RETRY
99 #define CONFIG_ZERO_BOOTDELAY_CHECK
100
101 #define CONFIG_NETMASK 255.255.255.0
102 #define CONFIG_IPADDR 10.0.0.110
103 #define CONFIG_SERVERIP 10.0.0.1
104
105 #if defined(CONFIG_CMD_KGDB)
106 #define CONFIG_KGDB_BAUDRATE 115200 /* speed to run kgdb serial port */
107 #endif
108
109 /*
110 * Miscellaneous configurable options
111 */
112 #define CONFIG_SYS_LONGHELP /* undef to save memory */
113 #define CONFIG_SYS_CBSIZE 256
114 /* Print Buffer Size */
115 #define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + \
116 sizeof(CONFIG_SYS_PROMPT)+16)
117 #define CONFIG_SYS_MAXARGS 16
118 #define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE
119
120 #define CONFIG_DISPLAY_CPUINFO /* Display cpu info */
121
122 #define CONFIG_SYS_MEMTEST_START 0x30000000 /* memtest works on */
123 #define CONFIG_SYS_MEMTEST_END 0x33F00000 /* 63 MB in DRAM */
124
125 #define CONFIG_SYS_LOAD_ADDR 0x30800000
126
127 /* support additional compression methods */
128 #define CONFIG_BZIP2
129 #define CONFIG_LZO
130 #define CONFIG_LZMA
131
132 /*-----------------------------------------------------------------------
133 * Physical Memory Map
134 */
135 #define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */
136 #define PHYS_SDRAM_1 0x30000000 /* SDRAM Bank #1 */
137 #define PHYS_SDRAM_1_SIZE 0x04000000 /* 64 MB */
138
139 #define PHYS_FLASH_1 0x00000000 /* Flash Bank #0 */
140
141 #define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1
142
143 /*-----------------------------------------------------------------------
144 * FLASH and environment organization
145 */
146
147 #define CONFIG_SYS_FLASH_CFI
148 #define CONFIG_FLASH_CFI_DRIVER
149 #define CONFIG_FLASH_CFI_LEGACY
150 #define CONFIG_SYS_FLASH_LEGACY_1Mx16
151 #define CONFIG_FLASH_SHOW_PROGRESS 45
152
153 #define CONFIG_SYS_MAX_FLASH_BANKS 1
154 #define CONFIG_SYS_FLASH_BANKS_LIST { CONFIG_SYS_FLASH_BASE }
155 #define CONFIG_SYS_MAX_FLASH_SECT (128)
156
157 #define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + 0x070000)
158 #define CONFIG_ENV_IS_IN_FLASH
159 #define CONFIG_ENV_SIZE 0x10000
160 /* allow to overwrite serial and ethaddr */
161 #define CONFIG_ENV_OVERWRITE
162
163 /*
164 * Size of malloc() pool
165 * BZIP2 / LZO / LZMA need a lot of RAM
166 */
167 #define CONFIG_SYS_MALLOC_LEN (4 * 1024 * 1024)
168
169 #define CONFIG_SYS_MONITOR_LEN (448 * 1024)
170 #define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_FLASH_BASE
171
172 /*
173 * NAND configuration
174 */
175 #ifdef CONFIG_CMD_NAND
176 #define CONFIG_NAND_S3C2410
177 #define CONFIG_SYS_S3C2410_NAND_HWECC
178 #define CONFIG_SYS_MAX_NAND_DEVICE 1
179 #define CONFIG_SYS_NAND_BASE 0x4E000000
180 #endif
181
182 /*
183 * File system
184 */
185 #define CONFIG_CMD_FAT
186 #define CONFIG_CMD_EXT2
187 #define CONFIG_CMD_UBI
188 #define CONFIG_CMD_UBIFS
189 #define CONFIG_CMD_MTDPARTS
190 #define CONFIG_MTD_DEVICE
191 #define CONFIG_MTD_PARTITIONS
192 #define CONFIG_YAFFS2
193 #define CONFIG_RBTREE
194
195 /* additions for new relocation code, must be added to all boards */
196 #define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1
197 #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x1000 - \
198 GENERATED_GBL_DATA_SIZE)
199
200 #define CONFIG_BOARD_EARLY_INIT_F
201
202 #endif /* __CONFIG_H */
编译执行:
do_date 对应着宏 DO_CMD_DATE,去掉此宏
再次编译执行,编译完成。
烧写进开发板。启动。
二、环境变量
2.1 修改分区为nand
环境变量的设置都会存在flash中,若是未设置分区,就执行save等保存命令,可能会破坏u-boot的启动程序。
环境变量的设置 对应着宏
不过这段我们不需要,我们需要设置自己的环境变量。
查找save命令的设置对应的文件,saveenv
我们只有nand和flash所以只对应这两行。查看common 下的 Makefile:
配置成保存环境变量的地方为 nand ,则需要定义宏 CONFIG_ENV_IS_IN_NAND
进入源文件继续查看,还需要定义宏 CMD_SAVEENV,CMD_SAVEENV宏的定义则依赖下面的程序:
CONFIG_CMD_NAND 我们已经在jz2440.h中定义,所以不需要了。
saveenv函数中同时涉及到另外两个宏:CONFIG_ENV_RANGE和CONFIG_ENV_OFFSET,一个是ENV的擦除大小,一个是偏移地址。
其中CONFIG_ENV_RANGE 的设置如上,我们可以直接参照 flash的设置,配置这几个宏。
编译,烧写:
结果不对,打开DEBUG开关进行DEBUG
代码流程中执行到initr_nand,之后就开始执行initr_env,在此函数和其子函数中加入调试代码 查看是否进入其中执行:
在函数的头尾加上debug函数,可以在进入的函数中都加上,然后去查函数在哪里调用出错了。编译,烧录:
上面是结尾的打印信息。根据上面的信息理一下代码
1 board_init_r
2 initr_env
3 debug("start of initr_env \n");
4 should_load_env()
5 debug("start of should_load_env() \n");
6 debug("end of should_load_env() \n");
7 env_relocate
8 debug("start of env_relocate(void) \n");
9 debug("in of env_relocate_spec() \n");
10 env_relocate_spec();
11 env_relocate_spec(void) //此函数是未定义CONFIG_ENV_OFFSET_REDUND宏的函数
12 debug("start of env_relocate(void) \n");
13 debug("env_relocate_spec in set_default_env\n");
14 set_default_env("!readenv() failed");
15 debug("end of env_relocate(void) \n");
16 debug("end of env_relocate(void) \n");
17 debug("end of initr_env \n");
标记红色部分是已经执行了的,可以看出在进入env_relocate_spec时候找不到函数了,此函数并没有进入,但是又确实执行到那一步了,看一下u-boot.dis,看是否执行过此函数
查看一下 env_relocate是否调用此地址函数:
这里又调用 但是执行的时候又出错了,进入了此函数,确没有返回。就是程序运行的时候根本没有进入此函数中。
查看一下栈的设置以及autoconf.h文件,发现在其中,打开了CONFIG_SYS_MALLOC_F宏,这个宏在原先的设置中我们并没有加入,应该是系统自动给他设定的。
查看jz2440_defconfig文件,发现里面确实打开了这个宏,注释掉,这个宏在栈的设置中会用到,在crt0.S的代码中有一段跳转到board_init_f_mem 函数,里面有一段代码如下:
1 #if defined(CONFIG_SYS_MALLOC_F) 2 top -= CONFIG_SYS_MALLOC_F_LEN; 3 gd->malloc_base = top; 4 #endif
这里是分配给一小段内存池,使栈下移动。栈往下多移动了 1024KB
同时在我们的默认的config文件中,发现关闭了 CONFIG_CMD_NAND 宏,这个宏必须要打开。
在配置中,SPL也被打开了,必须关闭
最后重新修改下crt0.S中的代码,如下:
1 ENTRY(_main)
2
3 /*
4 * Set up initial C runtime environment and call board_init_f(0).
5 * 初始化C运行环境并且调用 board_init_f(0) 函数
6 */
7
8 /*
9 * 初始化栈地址
10 */
11 #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
12 ldr sp, =(CONFIG_SPL_STACK)
13 #else
14 /* Generic-asm-offsets.h (include\generated)
15 * #define GENERATED_GBL_DATA_SIZE 192
16 * JZ2440.h(include\config)
17 * #define PHYS_SDRAM_1 0x30000000
18 * #define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1
19 * #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x1000 - GENERATED_GBL_DATA_SIZE)
20 *
21 * CONFIG_SYS_INIT_SP_ADDR = 0x30000000 + 0x1000 - 192(0xc0) = 0x30000f40
22 */
23 ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) /* 设置CFIG_SYS_INIT_SP_ADDR定义的地址,include/configs/jz2440.h中定义 */
24 #endif /* end defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)*/
25
26 #if defined(CONFIG_CPU_V7M) /* v7M forbids using SP as BIC destination */
27 mov r3, sp
28 bic r3, r3, #7
29 mov sp, r3
30 #else
31 /* sp 的8字节对齐 */
32 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
33 #endif /* end defined(CONFIG_CPU_V7M) */
34
35 /* 设置nand 启动 */
36 bl nand_init_ll /* 跳转到borad/samsung/jz2440/init.c 中执行 nand_init_ll 函数 */
37 mov r0, #0
38 ldr r1, =(CONFIG_SYS_TEXT_BASE) /*CONFIG_SYS_TEXT_BASE=0x33f00000 程序的链接地址*/
39 ldr r2, =0x80000 /* 程序大小 */
40 bl copy_code_to_sdram /* 拷贝代码到SDRAM */
41 bl clear_bss /* 清除bss */
42
43 ldr pc, =call_board_init_f /* 执行第一阶段初始化 */
44
45 call_board_init_f:
46 mov r0, sp /* r0 = sp */
47 bl board_init_f_mem /*跳转到 board_init_f_mem 执行*/
48 mov sp, r0 /* sp = 0x30000000*/
49
50 mov r0, #0
51 bl board_init_f /* 调用单板的初始化函数,跳转到 borad_init_f 处执行 */
52
53
54 #if ! defined(CONFIG_SPL_BUILD)
55
56
57 /*
58 * Set up intermediate environment (new sp and gd) and call
59 * relocate_code(addr_moni). Trick here is that we'll return
60 * 'here' but relocated.
61 */
62 /*
63 * 这一段代码是将board_init_f中设置好的start_addr_sp地址值赋给栈指针,使其指向重定位后的栈顶
64 * 8字节对齐后,将r9设为新的GD地址( gd地址=bd地址-sizeof(gd_t))
65 */
66 ldr sp, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */
67
68 #if defined(CONFIG_CPU_V7M) /* v7M forbids using SP as BIC destination */
69 mov r3, sp
70 bic r3, r3, #7
71 mov sp, r3
72 #else
73 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
74 #endif /* defined(CONFIG_CPU_V7M) */
75
76 ldr r9, [r9, #GD_BD] /* r9 = gd->bd */
77 sub r9, r9, #GD_SIZE /* new GD is below bd */
78
79 adr lr, here /*设置返回地址为下面的here,重定位到sdram后返回here运行*/
80 ldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off 取重定位地址偏移值 */
81 add lr, lr, r0 /*返回地址加偏移地址等于重定位后在sdram中的here地址*/
82
83 #if defined(CONFIG_CPU_V7M)
84 orr lr, #1 /* As required by Thumb-only */
85 #endif
86 #if 0
87 ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr 传入参数为重定位地址 */
88 b relocate_code /*跳到arch/arm/lib/relocate.S中执行*/
89 #endif
90
91 here: /*返回后跳到sdram中运行 */
92 /*
93 * now relocate vectors
94 */
95 bl relocate_vectors
96
97 /* Set up final (full) environment */
98 bl c_runtime_cpu_setup /* we still call old routine here */
99 #endif /* ! defined(CONFIG_SPL_BUILD) */
100
101 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FRAMEWORK)
102 #ifdef CONFIG_SPL_BUILD
103 /* Use a DRAM stack for the rest of SPL, if requested */
104 bl spl_relocate_stack_gd
105 cmp r0, #0
106 movne sp, r0
107 #endif /* end CONFIG_SPL_BULD */
108 ldr r0, =__bss_start /* this is auto-relocated! */
109
110 #ifdef CONFIG_USE_ARCH_MEMSET
111 ldr r3, =__bss_end /* this is auto-relocated! */
112 mov r1, #0x00000000 /* prepare zero to clear BSS */
113
114 subs r2, r3, r0 /* r2 = memset len */
115 bl memset
116 #else
117 ldr r1, =__bss_end /* this is auto-relocated! */
118 mov r2, #0x00000000 /* prepare zero to clear BSS */
119
120 clbss_l:cmp r0, r1 /* while not at end of BSS */
121 #if defined(CONFIG_CPU_V7M)
122 itt lo
123 #endif
124
125 strlo r2, [r0] /* clear 32-bit BSS word */
126 addlo r0, r0, #4 /* move to next */
127 blo clbss_l
128 #endif
129
130 #if ! defined(CONFIG_SPL_BUILD)
131 bl coloured_LED_init
132 bl red_led_on
133 #endif
134
135 /* call board_init_r(gd_t *id, ulong dest_addr) */
136 mov r0, r9 /* gd_t */
137 ldr r1, [r9, #GD_RELOCADDR] /* dest_addr */
138 /* ldr r1, =CONFIG_SYS_TEXT_BASE*/
139 /* call board_init_r */
140 ldr pc, =board_init_r /* this is auto-relocated! */
141
142 /* we should not return here. */
143 #endif
144
145 ENDPROC(_main)
再次编译运行,同时保存环境变量,并reset。
已经运行正常了。
reset后显示了一个错误,dm9000的地址未设置。下一节在修改,此时先看看env的启动流程。
2.2 env 的启动流程
uboot中env的整个架构可以分为3层:
(1) 命令层,如saveenv,setenv editenv这些命令的实现,还有如启动时调用的env_relocate函数。
(2) 中间封装层,利用不同静态存储器特性封装出命令层需要使用的一些通用函数,如env_init,env_relocate_spec,saveenv这些函数。实现文件在common/env_xxx.c
(3) 驱动层,实现不同静态存储器的读写擦等操作,这些是uboot下不同子系统都必须的。
2.2.1 env初始化
首先在board_init_f中调用init_sequence的env_init,这个函数是不同存储器实现的函数,nand中的实现如下:
1 int env_init(void)
2 {
3 gd->env_addr = (ulong)&default_environment[0]; /* 调用环境变量数组 */
4 gd->env_valid = 1; /* 设置env标志有效位为1 */
5 return 0;
6 }
env_init要早于静态存储器的初始化,所以无法进行env的读写,这里将gd中的env相关变量进行配置,默认设置env为valid。方便后面env_relocate函数进行真正的env从nand到ram的relocate。
2.2.2 initr_env
继续执行,在board_init_r中执行 initr_ebv
1 static int initr_env(void)
2 {
3 debug("start of initr_env \n");
4 /* initialize environment */
5 if (should_load_env())
6 env_relocate();
7 else
8 set_default_env(NULL);
9
10 /* Initialize from environment */
11 load_addr = getenv_ulong("loadaddr", 16, load_addr);
12 return 0;
13 }
这是在所有存储器初始化完成后执行的。
调用should_load_env:
1 static int should_load_env(void)
2 {
3 return 1;
4 }
返回 1之后执行下一句 env_relocate。
1 void env_relocate(void)
2 {
3 #if defined(CONFIG_NEEDS_MANUAL_RELOC)
4 env_reloc();
5 env_htab.change_ok += gd->reloc_off;
6 #endif
7 if (gd->env_valid == 0) {
8 #if defined(CONFIG_ENV_IS_NOWHERE) || defined(CONFIG_SPL_BUILD)
9 /* Environment not changable */
10 debug("in of set_default_env \n");
11 set_default_env(NULL);
12 #else
13 bootstage_error(BOOTSTAGE_ID_NET_CHECKSUM);
14 set_default_env("!bad CRC");
15 #endif
16 } else {
17 debug("in of env_relocate_spec() \n");
18 env_relocate_spec();
19 }
20 }
由于我们的 gd->env_valid 再board_init_f 函数中已经设置为1,这里会执行到 env_relocate_spec 函数中去。
CONFIG_ENV_OFFSET_REDUND此宏我们未设置,运行的代码就是如下:
1 void env_relocate_spec(void)
2 {
3 #if !defined(ENV_IS_EMBEDDED)
4 int ret;
5 ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
6
7 ret = readenv(CONFIG_ENV_OFFSET, (u_char *)buf);
8 if (ret) {
9 set_default_env("!readenv() failed");
10 return;
11 }
12
13 env_import(buf, 1);
14 debug("end 【nand】 of env_relocate_spec 2 \n");
15 #endif /* ! ENV_IS_EMBEDDED */
16 }
env_import 输出环境变量信息,至此已经结束。