プログラマーのクリスマス後-ゼロ
15391 ワード
u-boot-2014.10コード分析及び移植説明
_mainはcrt 0にある.Sでは,このセグメントは主にu−bootで最も根本的に最も重要な変数gdに空間を割り当て,クリアする.
gdは構造体変数であり、そのアドレスはr 9レジスタに格納され(記憶間違いがなければ、以前のバージョンはr 8レジスタに格納されていた)、u-bootプログラムで最も重要なグローバル情報、クロック関連変数、ページテーブル、再位置決め情報など、カーネルに伝達されるボードレベル情報も含まれている.
relocationの前に必要なスタック空間アドレスを定義し、board_に転送します.init_fプログラムは,ここからSPLであるBL 1フェーズコードとU-BOOTであるBL 2フェーズコードとが別々に異なるルートに進む.
CONFIG_が定義されていない場合SYS_GENERIC_BOARDは/arch/arm/lib/boardである.c
CONFIGが決まったらSYS_GENERIC_BOARD、common/board_f.c.
考えたら、まず/arch/arm/lib/board.cを例に挙げると、結局これは具体的なarchitectureに対してです(本当の原因はcommonの下で私はまだ見たことがありません)
ここでまたgdをクリアしたのは、ちょっと余計なようですが、SPL向けなのでしょうか.(common/board_f.cのため、このファイルの関数はgd初期化されていない)
gd->mon_lenはubootサイズです.
CONFIG_OF_EMBEDはdtbをuboot,libs-$(CONFIG_OF_EMBED)+=dts/
CONFIG_OF_SEPARATEもdtbを同時にコンパイルしていますが、別々にコンパイルしてubootに組み込まれていません.Makefileではわかりますが、なぜ_end後.
このセグメントは一部の初期化を行い、init_sequenceは関数ポインタ配列であり、
注意そこは実際には関数ポインタを指す配列であり,その利点は末尾のNULLであり,ポインタがNULLであることによって終了フラグとして判断される点である.以下、各初期化関数を逐一分析し、
1.arch_cpu_init
この関数は当然,各チップに対して独自に実現する必要があり,通常はこの関数においてcacheイネーブルの制御を実現することができる.
2.mark_bootstage
ubootの流れの中でタグをつけて、bootstage_mark_name関数は最終的に、プレートレベル自身が実現した1つの関数と接続することによって、印刷やledランプなどの様々な方法でubootに反応するプロセスを実現することができる.
3.fdtdec_check_fdt
fdtが存在するかどうかを検出する
4.board_early_init_f
初期化のいくつか
必要に応じて、マクロCONFIG_を定義します.BOARD_EARLY_INIT_F、そしてこの関数を実現する
5.timer_init
timer初期化,題外:u-bootにおけるtimer駆動の役割はdelayを実現するためであるため,timer駆動もudelayをめぐって展開される.
6.board_postclk_init
初期クロック関連初期化
必要に応じて、マクロCONFIG_を定義します.BOARD_POSTCLK_INIT、そしてこの関数を実現する
7.get_clocks
実際には主にgd->archを取得するために見える.sdhc_clkクロック、すなわちsdmmcクロックを取得するためですが、必要ではありません.
必要に応じて、マクロCONFIG_を定義します.FSL_ESDHCは、この関数を実装します.
8.env_init
gdの2つのメンバー、すなわち環境変数テーブルのアドレス、valid値を初期化する
9.init_baudrate
gdにおけるボーレートメンバー変数の初期化
ここでBAUDRATEのマクロ定義を設計する
10.serial_init
シリアルポート駆動の初期化
対応するシリアルポートドライバに追加する必要がある2つの関数default_serial_コンソール、およびserial_デバイス構造体のstartメンバー関数
11.console_init_f
実は何もなくて、ただ存在するCONFIG_PRE_CONSOLE_BUFFERの場合はbuffer初期化のプロセスがあります
12.display_banner
ubootバージョン情報等の印刷
13.print_cpuinfo
これは各チップが自分で実現し、cpu関連情報を印刷します.
14.checkboard
board関連情報の印刷
15.init_func_i2c
i 2 cが必要であれば初期化
16.dram_init
自己実現、gd->ram_sizeの初期化、もちろんありますよねdram_bankの初期化はここに書いてあります
全体init_sequence初期化は終了しました.
残りは次号にしよう.
1 ENTRY(_main)
2
3 /*
4 * Set up initial C runtime environment and call board_init_f(0).
5 */
6
7 #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
8 ldr sp, =(CONFIG_SPL_STACK)
9 #else
10 ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
11 #endif
12 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
13 mov r2, sp
14 sub sp, sp, #GD_SIZE /* allocate one GD above SP */
15 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
16 mov r9, sp /* GD is above SP */
17 mov r1, sp
18 mov r0, #0
1 clr_gd:
2 cmp r1, r2 /* while not at end of GD */
3 strlo r0, [r1] /* clear 32-bit GD word */
4 addlo r1, r1, #4 /* move to next */
5 blo clr_gd
_mainはcrt 0にある.Sでは,このセグメントは主にu−bootで最も根本的に最も重要な変数gdに空間を割り当て,クリアする.
gdは構造体変数であり、そのアドレスはr 9レジスタに格納され(記憶間違いがなければ、以前のバージョンはr 8レジスタに格納されていた)、u-bootプログラムで最も重要なグローバル情報、クロック関連変数、ページテーブル、再位置決め情報など、カーネルに伝達されるボードレベル情報も含まれている.
1 #if defined(CONFIG_SYS_MALLOC_F_LEN) && !defined(CONFIG_SPL_BUILD)
2 sub sp, sp, #CONFIG_SYS_MALLOC_F_LEN
3 str sp, [r9, #GD_MALLOC_BASE]
4 #endif
5 /* mov r0, #0 not needed due to above code */
6 bl board_init_f
relocationの前に必要なスタック空間アドレスを定義し、board_に転送します.init_fプログラムは,ここからSPLであるBL 1フェーズコードとU-BOOTであるBL 2フェーズコードとが別々に異なるルートに進む.
CONFIG_が定義されていない場合SYS_GENERIC_BOARDは/arch/arm/lib/boardである.c
CONFIGが決まったらSYS_GENERIC_BOARD、common/board_f.c.
考えたら、まず/arch/arm/lib/board.cを例に挙げると、結局これは具体的なarchitectureに対してです(本当の原因はcommonの下で私はまだ見たことがありません)
1 void board_init_f(ulong bootflag)
2 {
3 bd_t *bd;
4 init_fnc_t **init_fnc_ptr;
5 gd_t *id;
6 ulong addr, addr_sp;
7 #ifdef CONFIG_PRAM
8 ulong reg;
9 #endif
10 void *new_fdt = NULL;
11 size_t fdt_size = 0;
12
13 memset((void *)gd, 0, sizeof(gd_t));
ここでまたgdをクリアしたのは、ちょっと余計なようですが、SPL向けなのでしょうか.(common/board_f.cのため、このファイルの関数はgd初期化されていない)
1 gd->mon_len = (ulong)&__bss_end - (ulong)_start;
2 #ifdef CONFIG_OF_EMBED
3 /* Get a pointer to the FDT */
4 gd->fdt_blob = __dtb_dt_begin;
5 #elif defined CONFIG_OF_SEPARATE
6 /* FDT is at end of image */
7 gd->fdt_blob = &_end;
8 #endif
9 /* Allow the early environment to override the fdt address */
10 gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,
11 (uintptr_t)gd->fdt_blob);
gd->mon_lenはubootサイズです.
CONFIG_OF_EMBEDはdtbをuboot,libs-$(CONFIG_OF_EMBED)+=dts/
CONFIG_OF_SEPARATEもdtbを同時にコンパイルしていますが、別々にコンパイルしてubootに組み込まれていません.Makefileではわかりますが、なぜ_end後.
1 for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
2 if ((*init_fnc_ptr)() != 0) {
3 hang ();
4 }
5 }
このセグメントは一部の初期化を行い、init_sequenceは関数ポインタ配列であり、
1 init_fnc_t *init_sequence[] = {
2 arch_cpu_init, /* basic arch cpu dependent setup */
3 mark_bootstage,
4 #ifdef CONFIG_OF_CONTROL
5 fdtdec_check_fdt,
6 #endif
7 #if defined(CONFIG_BOARD_EARLY_INIT_F)
8 board_early_init_f,
9 #endif
10 timer_init, /* initialize timer */
11 #ifdef CONFIG_BOARD_POSTCLK_INIT
12 board_postclk_init,
13 #endif
14 #ifdef CONFIG_FSL_ESDHC
15 get_clocks,
16 #endif
17 env_init, /* initialize environment */
18 init_baudrate, /* initialze baudrate settings */
19 serial_init, /* serial communications setup */
20 console_init_f, /* stage 1 init of console */
21 display_banner, /* say that we are here */
22 print_cpuinfo, /* display cpu info (and speed) */
23 #if defined(CONFIG_DISPLAY_BOARDINFO)
24 checkboard, /* display board info */
25 #endif
26 #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C)
27 init_func_i2c,
28 #endif
29 dram_init, /* configure available RAM banks */
30 NULL,
31 };
注意そこは実際には関数ポインタを指す配列であり,その利点は末尾のNULLであり,ポインタがNULLであることによって終了フラグとして判断される点である.以下、各初期化関数を逐一分析し、
1.arch_cpu_init
この関数は当然,各チップに対して独自に実現する必要があり,通常はこの関数においてcacheイネーブルの制御を実現することができる.
2.mark_bootstage
1 /* Record the board_init_f() bootstage (after arch_cpu_init()) */
2 static int mark_bootstage(void)
3 {
4 bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_F, "board_init_f");
5
6 return 0;
7 }
ubootの流れの中でタグをつけて、bootstage_mark_name関数は最終的に、プレートレベル自身が実現した1つの関数と接続することによって、印刷やledランプなどの様々な方法でubootに反応するプロセスを実現することができる.
3.fdtdec_check_fdt
fdtが存在するかどうかを検出する
4.board_early_init_f
初期化のいくつか
必要に応じて、マクロCONFIG_を定義します.BOARD_EARLY_INIT_F、そしてこの関数を実現する
5.timer_init
timer初期化,題外:u-bootにおけるtimer駆動の役割はdelayを実現するためであるため,timer駆動もudelayをめぐって展開される.
6.board_postclk_init
初期クロック関連初期化
必要に応じて、マクロCONFIG_を定義します.BOARD_POSTCLK_INIT、そしてこの関数を実現する
7.get_clocks
実際には主にgd->archを取得するために見える.sdhc_clkクロック、すなわちsdmmcクロックを取得するためですが、必要ではありません.
必要に応じて、マクロCONFIG_を定義します.FSL_ESDHCは、この関数を実装します.
8.env_init
gdの2つのメンバー、すなわち環境変数テーブルのアドレス、valid値を初期化する
9.init_baudrate
gdにおけるボーレートメンバー変数の初期化
ここでBAUDRATEのマクロ定義を設計する
10.serial_init
シリアルポート駆動の初期化
対応するシリアルポートドライバに追加する必要がある2つの関数default_serial_コンソール、およびserial_デバイス構造体のstartメンバー関数
11.console_init_f
実は何もなくて、ただ存在するCONFIG_PRE_CONSOLE_BUFFERの場合はbuffer初期化のプロセスがあります
12.display_banner
ubootバージョン情報等の印刷
13.print_cpuinfo
これは各チップが自分で実現し、cpu関連情報を印刷します.
14.checkboard
board関連情報の印刷
15.init_func_i2c
i 2 cが必要であれば初期化
16.dram_init
自己実現、gd->ram_sizeの初期化、もちろんありますよねdram_bankの初期化はここに書いてあります
全体init_sequence初期化は終了しました.
残りは次号にしよう.