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函式用的。