u-boot移植(十三)---代碼修改---裁剪及環境變量 一
一、內核裁剪
內核的裁剪首先就是修改我們的配置文件,即 include/configs/jz2440.h 文件,裏面定義的很多宏,我們也許用不上的就要去掉。
1 /*
2 * (C) Copyright 2002
3 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
4 * Marius Groeger <[email protected]>
5 * Gary Jennejohn <[email protected]>
6 * David Mueller <[email protected]
編譯執行:
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 輸出環境變量信息,至此已經結束。
u-boot移植(十三)---代碼修改---裁剪及環境變量 一