八、uboot 代碼流程分析---C環境建立


8.1 start.S 修改

  發現啟動初始化的過程需要屏蔽看門狗和中斷。

  如果看門狗不禁用,會導致系統反復重啟,因此需要在初始化的時候禁用看門狗;中斷屏蔽保證啟動過程中不出現異常現象

  時鍾不需要初始化,直接由外部晶振提供初始化,在第二階段 C 部分再進行初始化。

  代碼主要在 start.S 中進行修改,主要是時鍾代碼的刪除:

  

 

   這一塊代碼刪除掉。

8.2 _main --- C環境

  執行完一系列初始化后,開始跳轉到 _main 中執行進行C環境初始化和第二階段的代碼  

  crt0.S (arch\arm\lib) 

  _main 執行過程如下:

  1. 建立調用 board_init_f() 的環境,此環境只是提供一個用來保存全局變量 GD 結構體的棧和空間,棧和空間都位於 SRAM 中。在調用board_init_f()前,GD 需要被清 0。
  2. 調用 board_init_f(),該函數從系統RAM(DRAM,DDR ...)准備將要執行的硬件。由於系統RAM可能還不可用,因此board_init_f()必須使用當前的GD來存儲必須傳遞到后面階段的任何數據。 這些數據包括重定位目標,未來堆棧和未來的GD位置。
  3. 設置中間環境,其中堆棧和GD是由系統RAM中的board_init_f()分配的,但BSS和初始化的 non-const 數據仍然不可用。
  4. 對於U-Boot本身(不是SPL),調用relocate_code()。 該函數將U-Boot從其當前位置重定位到由board_init_f()計算的重定位地址。
  5. 設置調用board_init_r()的最終環境。 這個環境具有BSS(初始化為0),初始化的 non-const 數據(初始化為其預期值),和系統RAM中的堆棧(用於SPL將堆棧和GD移入RAM是可選的 - 參見CONFIG_SPL_STACK_R)。 GD保留由board_init_f()設置的值。
  6. 對於U-Boot(不是SPL),有些CPU在內存方面還有一些工作要做,所以調用c_runtime_cpu_setup。
  7. 最后 跳到 board_init_r() 去執行

8.2.1 設置棧並初始化GD 和全局數據

 1 #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
 2     ldr    sp, =(CONFIG_SPL_STACK)
 3 #else
 4     ldr    sp, =(CONFIG_SYS_INIT_SP_ADDR)  /** CONFIG_SYS_INIT_SP_ADDR = 0x3000 0f40 */
 5 #endif  /** end defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) */
 6 #if defined(CONFIG_CPU_V7M)    /* v7M forbids using SP as BIC destination */
 7     mov    r3, sp
 8     bic    r3, r3, #7
 9     mov    sp, r3
10 #else
11     bic    sp, sp, #7    /* 8 字節對齊,將 sp 的低三位清零,還是 0x3000 0f40 */
12 #endif  /** end defined(CONFIG_CPU_V7M)     */
13     mov    r0, sp
14     bl    board_init_f_alloc_reserve  /** 預留 GD 的空間 */
15     mov    sp, r0
16     /* set up gd here, outside any C code */
17     mov    r9, r0
18     bl    board_init_f_init_reserve   /** 對 GD 做了次初始化,棧指針不動 */
19 
20     mov    r0, #0
21     bl    board_init_f    /** 進入 relocate 前的初始化 */

8.2.2 board_init_f_alloc_reserve 

 1 ulong board_init_f_alloc_reserve(ulong top)
 2 {
 3     /* Reserve early malloc arena */
 4 #if defined(CONFIG_SYS_MALLOC_F)
 5     /** 從頂部向下分配一塊 CONFIG_SYS_MALLOC_F_LEN 大小的空間給 early malloc 使用,
 6         這塊內存是用於在relocation前用於給malloc函數提供內存池 
 7         0x3000 0f40 - 0x400  = 0x3000 0b40*/
 8     top -= CONFIG_SYS_MALLOC_F_LEN;
 9 #endif
10     /** 分配 sizeof(struct global_data) 大小的內存給 global_data 使用,向下 16byte 對齊
11         global_data 的長度會根據我們的配置變化長度,這里沒辦法計算分配后的地址所在 */
12     top = rounddown(top-sizeof(struct global_data), 16);
13 
14     return top;
15 }

8.2.4 board_init_f_init_reserve

 1 void board_init_f_init_reserve(ulong base)
 2 {
 3     struct global_data *gd_ptr;
 4 #ifndef _USE_MEMCPY
 5     int *ptr;
 6 #endif
 7 
 8     /*
 9      * clear GD entirely and set it up.
10      * Use gd_ptr, as gd may not be properly set yet.
11      */
12     /** gd_ptr 地址等於當前棧所在的地址 */
13     gd_ptr = (struct global_data *)base;
14     /* zero the area */
15 #ifdef _USE_MEMCPY
16     /** 初始化 */
17     memset(gd_ptr, '\0', sizeof(*gd));
18 #else
19     for (ptr = (int *)gd_ptr; ptr < (int *)(gd_ptr + 1); )
20         *ptr++ = 0;
21 #endif
22     /* set GD unless architecture did it already */
23 #if !defined(CONFIG_ARM)
24     arch_setup_gd(gd_ptr);
25 #endif
26     /* next alloc will be higher by one GD plus 16-byte alignment */
27     /** 分配空間,並向上 16 字節對齊,這里又指向了  0x3000 0b40 處 */
28     base += roundup(sizeof(struct global_data), 16);
29 
30     /*
31      * record early malloc arena start.
32      * Use gd as it is now properly set for all architectures.
33      */
34 
35 #if defined(CONFIG_SYS_MALLOC_F)
36     /* go down one 'early malloc arena' */
37     gd->malloc_base = base;
38     /* next alloc will be higher by one 'early malloc arena' size,
39        base 重新回到 0x3000 0f40*/
40     base += CONFIG_SYS_MALLOC_F_LEN;
41 #endif
42 }

8.2.5 global_data內存分布

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM