程式員的聖誕節後-零

來源:互聯網
上載者:User

標籤:

u-boot-2014.10程式碼分析及移植說明

 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 #else10     ldr    sp, =(CONFIG_SYS_INIT_SP_ADDR)11 #endif12     bic    sp, sp, #7    /* 8-byte alignment for ABI compliance */13     mov    r2, sp14     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, sp18     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位於crt0.S中,該段主要是給u-boot中最根本最重要的變數gd分配空間並清零。

gd是一個結構體變數,其地址被放置於r9寄存器中(如果沒記錯的話,以前的版本是放入r8寄存器的),它包含了u-boot程式中最重要的全域資訊,包括時鐘相關變數,頁表,重定位資訊等,另外還包括傳遞給核心的板級資訊。

1 #if defined(CONFIG_SYS_MALLOC_F_LEN) && !defined(CONFIG_SPL_BUILD)2     sub    sp, sp, #CONFIG_SYS_MALLOC_F_LEN3     str    sp, [r9, #GD_MALLOC_BASE]4 #endif5     /* mov r0, #0 not needed due to above code */6     bl    board_init_f

定義relocation之前所需的堆空間地址,之後轉入board_init_f程式,從此處起,SPL即BL1階段代碼和U-BOOT即BL2階段代碼分開走向了不同的路線。

如果未定義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 #endif10     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 #endif10     timer_init,        /* initialize timer */11 #ifdef CONFIG_BOARD_POSTCLK_INIT12     board_postclk_init,13 #endif14 #ifdef CONFIG_FSL_ESDHC15     get_clocks,16 #endif17     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 #endif26 #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C)27     init_func_i2c,28 #endif29     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函數最終可以通過和板級自己實現的一個函數掛接,實現通過列印或者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中的兩個成員,即環境變數表的地址,以及valid值

9.init_baudrate

初始化gd中的傳輸速率成員變數

該處設計BAUDRATE的一個宏定義

10.serial_init

初始化串口驅動

對應串口驅動中必須添加的兩個函數default_serial_console,以及serial_device結構體的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

如果有且需要i2c的話,初始化

16.dram_init

自己實現,gd->ram_size的初始化,當然也有吧dram_bank的初始化寫在這裡

整個init_sequence初始化就結束了。

剩下的下期再說。

 

程式員的聖誕節後-零

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.