1. 程式人生 > 其它 >uboot移植之重定位之前的啟動過程

uboot移植之重定位之前的啟動過程

uboot啟動的第一階段是cpu架構相關的初始化,用匯編完成,從arch/arm/cpu/arm920t/s3c24x0目錄下的start.S檔案開始看:

程式碼一開始就跳轉到start_code:

1、把cpu設為管理模式

為什麼要設定成管理模式:https://blog.csdn.net/rheostat/article/details/7734407

2、關看門狗

3、遮蔽中斷

4、設定時鐘分頻係數

5、呼叫cpu_init_crit函式

cpu_init_crit函式關閉了cache和mmu之後,呼叫lowlevel_init函式,在lowlevel_init裡面初始化SDRAM。

6、設定棧,跳轉到c函式board_init_f函式執行

board_init_f函式做的事:

①、遍歷一個指標陣列,迴圈呼叫各個初始化函式,如果這些初始化函式的返回值有一個不等於0,說明初始化出錯,cpu陷入死迴圈函式hang()

指標陣列成員如下:

 1 init_fnc_t *init_sequence[] = {
 2     board_early_init_f,
 3     timer_init,        /* initialize timer */
 4     env_init,        /* initialize environment */
 5     init_baudrate,        /* initialze baudrate settings 
*/ 6 serial_init, /* serial communications setup */ 7 console_init_f, /* stage 1 init of console */ 8 display_banner, /* say that we are here */ 9 print_cpuinfo, /* display cpu info (and speed) */ 10 };

②、把指標gd指向之前棧指標指向的地址0x30000f80,並把gd指標強制轉化的gd_t結構體指標,從而設定各種引數(gd的意思是global_data):

設定引數程式碼:

1 memset((void *)gd, 0, sizeof(gd_t));//初始化結構體內容為0
2 gd->mon_len = _bss_end_ofs;
3 gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16(uintptr_t)gd->fdt_blob);    
4 gd->tlb_addr = addr;    
5 ...
6 ...

③、把gd_t結構體搬移到地址為id的地方

  id也是設定gd_t結構體的過程中得到的,所以一開始只能把gd_t結構體暫時放在原先設定的棧頂位置,等gd_t結構體設定完了再搬過去。

④、最後呼叫重定位函式relocate_code,三個引數從左到右依次賦值給暫存器R0,R1,R2

addr_sp:新設定的棧指標地址

id:gd_t結構體所在的地址

addr:需要把uboot複製到的地址

addr一開始指向64M SDRAM的最高地址0x34000000,從最高地址開始安排記憶體分佈,為各個外設保留記憶體區域,最後addr指向的地址就是為uboot開闢的記憶體空間的起始地址;

而addr_sp是所有記憶體安排完了以後,指向的空餘記憶體空間的最高地址(棧向下生長);

id引數是為了uboot重定位完成之後,傳給board_init_r函式用的。