Bootloader详解
Bootloader基本認識
每一種不同的CPU系統結構都有不同的BootLoader,除了依賴于CPU的體系結構外,Bootloader還依賴于具體的嵌入式板級設備的配置,比如板卡的硬件地址分配,外設芯片的類型等。也就是說,對于兩塊不同的開發板而言,即使他們是基于同一種CPU而構建的,但如果他們的硬件資源或配置不一樣的話,想要在一塊開發板上運行的Bootloader程序也能在另一塊開發板上運行的話,Bootloader仍然需要修改。
BootLoader的啟動過程分為單階段(Single-stage)和多階段(Multi-Stage)兩種,通常多階段的BootLoader具有更復雜的功能,更好的可移植性。從固態存儲設備上的Bootloader大多采用兩階段,即啟動過程分為Stage1和Stage2:
stage1:完成初始化硬件,為stage2準備內存空間,并將stage2復制到內存中,設置stage2運行需要的堆棧,然后跳轉到stage2運行。注意:在該階段執行bootloader代碼時,C語言的運行環境還沒建立起來(主要是堆棧還沒設置好,所以該階段的代碼都是采用匯編語言編寫)
stage2:初始化本階段要使用到的硬件設備,將內核映像(鏡像)和根文件系統映像(鏡像)從flash上讀到RAM中,然后調用內核。注意:stage1階段已經為該階段建立好了C語言的運行環境,所以該階段大多采用C語言編寫,當然也可以用匯編!
?
知識擴展
一、堆棧空間分配區別:
? ? ? ?1、棧(習慣上也稱為堆棧):由操作系統自動分配釋放,存放函數的參數值,局部變量的值等;
2、堆: 由程序員動態分配和釋放,若程序員不釋放,程序結束時可能由OS回收,分配方式倒是類似于鏈表。
二、堆棧緩存方式區別:
1、棧使用的是一級緩存,他們通常都是被調用時處于存儲空間中,調用完畢立即釋放;
2、堆是存放在二級緩存中,生命周期由虛擬機的垃圾回收算法來決定(并不是一旦成為孤兒對象就能被回收)。所以調用這些對象的速度要相對來得低一些。
三、堆棧數據結構區別:
堆(數據結構):堆可以被看成是一棵樹,如:堆排序;
棧(數據結構):一種先進后出的數據結構。
“?!暗纳钊肜斫?/h1>
1.什么是棧?
棧(也稱為堆棧,注意和堆的區別)是一種特殊的線性表,是一種只允許在表的一端進行插入或刪除操作的線性表。表中允許進行插入、刪除操作的一端稱為棧頂。表的另一端稱為棧底。棧頂的當前位置是動態的,對棧頂當前位置的標記稱為棧頂指針。當棧中沒有數據元素時,稱之為空棧。棧的插入操作通常稱為進?;蛉霔?#xff0c;棧的刪除操作通常稱為退棧或出棧。
簡易理解:
客棧,即臨時寄存的地方,計算機中的堆棧主要用來保存臨時數據,局部變量和中斷/調用子程序程序的返回地址。程序中棧主要是用來存儲函數中的局部變量以及保存寄存器參數的,如果你用了操作系統,棧中還可能存儲當前進線程的上下文。設置棧大小的一個原則是,保證棧不會下溢出到數據空間或程序空間.CPU在運行程序時,會自動的使用堆棧,所以堆棧指針SP就必須要在調用C程序前設定。
CPU的內存RAM空間存放規律一般是分段的,從地址向高地址,依次為:程序段(.text),BSS段,然后上面還可能會有堆空間,然后最上面才是堆棧段,這樣安排堆棧,是因為堆棧的特點決定的,所以堆棧的指針SP初始化一般在堆棧段的高地址,也就是內存的高地址,然后讓堆棧指針向下增長(其實就是遞減)。這樣做的好處就是堆棧空間遠離了其他段,不會跟其他段重疊,造成修改其他段數據,而引起不可預料的后果,還有設置堆棧大小的原則,要保證棧不會下溢出到數據空間或者程序空間。所謂堆棧溢出,是指堆棧指針SP向下增長到其他段空間,如果棧指針向下增長到其他段空間,稱為堆棧溢出。堆棧溢出會修改其他空間的值,嚴重情況下可造成死機.
2.堆棧指針的設置
開始將堆棧指針設置在內部RAM,是因為不是每個板上都有外部RAM,而且外部RAM的大小也不相同,而且如果是SDRAM,還需要初始化,在內部RAM開始運行的一般是一個小的引導程序,基本上不怎么使用堆棧,因此將堆棧設置在內部RAM,但這也就要去改引導程序不能隨意使用大量局部變量。
片內4K的SRAM,SDRAM大小64M,從0x30000000到0x33FFFFFF,當程序在片內SRAM運行的時候,sp的值設置為4096,當程序在SDRAM內運行的時候sp設置為0x34000000,當然當程序在內部SRAM運行,若已經初始化SDRAM,此時也可以將堆棧指針設置為0x34000000,更加防止了堆棧溢出。
3. ?棧的整體作用
1) 保存現場;
2) 傳遞參數:匯編代碼調用 C 函數時,需傳遞參數;
3) 保存臨時變量:包括函數的非靜態局部變量以及編譯器自動生成的其他臨時變量;
1) ?保存現場
現場,意思就相當于案發現場,總有一些現場的情況,要記錄下來的,否則被別人破壞掉之后,你就無法恢復現場了。而此處說的現場,就是指 CPU 運行的時候,用到了一些寄存器,比如 r0,r1 等等,對于這些寄存器的值,如果你不保存而直接跳轉到子函數中去執行,那么很可能就被其破壞了,因為其函數執行也要用到這些寄存器。因此,在函數調用之前,應該將這些寄存器等現場,暫時保持起來(入棧 push),等調用函數執行完畢返回后(出棧 pop),再恢復現場。這樣CPU就可以正確的繼續執行了。保存寄存器的值,一般用的是 push 指令,將對應的某些寄存器的值,一個個放到棧中,把對應的值壓入到棧里面,即所謂的壓棧。然后待被調用的子函數執行完畢的時候,再調用 pop,把棧中的一個個的值,賦值給對應的那些你剛開始壓棧時用到的寄存器,把對應的值從棧中彈出去,即所謂的出棧。其中保存的寄存器中,也包括 lr 的值(因為用 bl 指令進行跳轉的話,那么之前的 PC 的值是存在 lr 中的),然后在子程序執行完畢的時候,再把棧中的 lr 的值 pop 出來,賦值給 PC,這樣就實現了子函數的正確的返回
2) ?傳遞參數
C 語言進行函數調用的時候,常常會傳遞給被調用的函數一些參數,對于這些 C 語言級別的參數,被編譯器翻譯成匯編語言的時候,就要找個地方存放一下,并且讓被調用的函數能夠訪問,否則就沒發實現傳遞參數了。對于找個地方放一下,分兩種情況。一種情況是,本身傳遞的參數不多于 4 個,就可以通過寄存器 r0~r3 傳送參數。因為在前面的保存現場的動作中,已經保存好了對應的寄存器的值,那么此時,這些寄存器就是空閑的,可以供我們使用的了,那就可以放參數。另一種情況是,參數多于 4 個時,寄存器不夠用,就得用棧了。
3) ?臨時變量保存在棧中
包括函數的非靜態局部變量以及編譯器自動生成的其他臨時變量。
?
?
?
總結
以上是生活随笔為你收集整理的Bootloader详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 几种添加系统环境变量方法和区别
- 下一篇: DSP仿真器原理