bootloader啟動過程詳細說明
今天早上看了一上午的bootloader簡單原始碼,終於捋順了bootloader的執行過程,之前只是知道bootloader程式碼會先被irom中的程式碼拷貝到iram中一部分,然後執行這部分程式碼,會把整個bootloader程式碼拷貝到sdram中,最終在sdram執行剩下的程式碼,而這段程式碼會把kernel拷貝到sdram的某個地址,最終引導起來整個核心。但是我今天早上看程式碼的時候看到一個問題,我所有的程式碼都是自己動手實現的,只要一步一步按照順序來,不就可以實現麼?為什麼還要拷貝來拷貝去的。感覺直接按照跳轉的方式,跳轉值進行指令的跳轉就行,但是想過之後,我意識到自己真是無知了。比如說在irom中執行的時候,會有一次跳轉到iram中某一個地址,當然pc是肯定可以直接跳轉到指定的任何一個地址,但是在這個地址中沒有存放指令碼,這時候,肯定是一個有去無回的過程,不僅這樣,這個pc跳到這裡後,就會很迷茫,前不著村,後不著店的,不知道自己的所去所從,就會死到這裡。只有先把程式碼拷貝到將要跳轉的地址中,pc指標才會順著跳轉後的指令繼續執行,也就是說每一個指令都要負責人,確保執行完這個指令後,一定要有另一個指令去接納pc。這樣pc才會一直活在我的程式碼中。
下邊我就再把我更進一步瞭解到的bootloader執行過程再重新敘述一下:
我使用的是s5pv210晶片、K9K8G08U0A型號的nand flash
第一步:cpu啟動起來後,先來到0x00000000這個地址處(也就是irom的地址),此時會看到有一段程式碼(這是irom中固定的程式碼)在這裡,這段程式碼會找到bootloader的第一段程式碼(以下就稱為BL1)存放的地址,由於BL1存放在nand flash中,不支援片上執行,所以irom會把這段程式碼拷貝到iram中,
但是在拷貝之前,irom會先把iram的起始4個地址分別寫上一定的內容(不過通常只寫0x00地址為BL1所佔空間的大小(一般是8k),而其他三個地址全寫為0),把BL1這段程式碼拷貝到iram後,irom的使命就快要完成了,irom的最後一個任務就是把pc指標指向放BL1的那塊地址的起始位置,然後就按照這個地址的指令開始執行。
第二步
在初始化所有需要初始化的硬體後,BL1還會有一個拷貝指令,就是要把bootloader拷貝到sdram中一般會把bootloader的程式碼放到BLADD(表示為bootloader在sdram中存放的地址。
這時候BL1的使命也將要完成,於是,BL1會把pc指標跳轉到BL2的地址,此時所有要執行的程式碼都在sdram中,這次的跳轉不會直接從這次拷貝的開始地址執行,而是跳過BL1程式碼所佔的地址,從BL2開始執行。
第三步:執行BL2中的程式碼。此時BL2程式碼的功能主要是實現MTD裝置驅動初始化,電源、時鐘初始化,堆疊空間,以及各種必要的初始化,並且會提供一個命令列,可以進行互動。在這之後會有一個設定核心引數的過程,這些引數在記憶體中的存在方式也是以結構體儲存,以連結串列進行關聯的,而這個 連結串列有一個固定的起始地址-0x3000_0100;每一個結構體代表一個資訊,並首尾相連,核心在需要這些引數時,就可以再對應的地址上取資料。這一步執行完畢後,就要把kernel的程式碼拷貝到sdram中的一個指定地址,並且會把這個地址強制轉換成一個函式指標,並且向這個函式中傳遞一些引數,最終會到核心中執行核心程式碼。這個時候,核心就會被引導到執行狀態。
這就是我今天大半天的心得,寫出來,看到這篇文章的你,肯定也是對這方面感興趣的,希望可以互相交流,盡情來吐槽我的這篇文章吧,把你所認為不對或者我沒有想到的內容告訴我,大家共同進步!