16.U-boot的工作流程分析-2440

16.U-boot的工作流程分析-2440

分析的流程:

  1. 程序入口
  2. 第一階段程序分析
  3. 第二階段程序分析

2440開發板:

1.uboot的入口:

要看uboot工程的入口,首先打開頂層目錄的Makefile:

Uboot所支持的開發板,在頂層的Makefile中都會有一個配置選項。比如2440,在Makefile中的配置選項是smdk2440_config:在vim的命令模式按下/,然后輸入smdk6410_config回車會定位到這里:

這是Makefile里的一個目標。這是來配置2440開發板的。看到上圖第二行的smdk2440,這個參數決定了開發板的名稱。這個名稱是有作用的。接下來看看他的作用。

首先是找一下目錄:

可以看到這里有很多smdk的子目錄,也包括smdk2440,這兩個是對應的。該目錄存放的就是2440開發板相關的文件。里面有一個叫uboot.lds的文件,前面知道lds文件是連接器腳本。Uboot的整個過程的鏈接,是通過該腳本來鏈接控制的。打開該鏈接器腳本:

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")

OUTPUT_ARCH(arm)

ENTRY(_start)

SECTIONS

{

????. = 0x00000000;

????. = ALIGN(4);

????.text :

????{

???? cpu/s3c24xx/start.o????(.text) //1可以看到位于代碼段前端的文件是start.o,對應的是一個匯編文件。這個匯編文件會最先被運行。但是這個匯編代碼里最先執行的代碼是哪些呢?

???? cpu/s3c24xx/s3c2440/cpu_init.o????(.text)

???? *(.text)

????}

????. = ALIGN(4);

????.rodata : { *(.rodata) }

????. = ALIGN(4);

????.data : { *(.data) }

????. = ALIGN(4);

????.got : { *(.got) }

?

????. = .;

????__u_boot_cmd_start = .;

????.u_boot_cmd : { *(.u_boot_cmd) }

????__u_boot_cmd_end = .;

?

????. = ALIGN(4);

????.mmudata : { *(.mmudata) }

?

????. = ALIGN(4);

????__bss_start = .;

????.bss : { *(.bss) }

????_end = .;

}

首先是找到該文件:

上面u-boot-lds文件里,在sections的標識之上,有一行:ENTRY(_start)是整個程序的入口。所以就找找start.S文件里有沒_start這個標識呢?一搜會馬上看到該標號:

到這里,看到這個_start才是整個uboot工程的入口。

?

接下來是第一階段的代碼:

在Linux里,打開上一節創建好的,Source Insight里的uboot工程:

然后找到smdk2440的start.S:

接下來看uboot做了什么事,主要是通過注釋來分析:

開發板一上電,它會跳轉到start.S的中斷向量表的開始處執行:

從它的注釋:

所以1,:知道上電后是跳到中斷向量表來執行。執行的第一條指令是b start_code。

Start_code的實在start.S的下面定義的:

從注釋知道,這是actual start code。進入之后,set the cpu to svc32 mode,設置cpu為SVC模式。

接著執行的代碼是:

3.刷新I/D caches。

4.然后是關閉MMU和cache:

后加

關閉系統時鐘,在lowlevel _init函數里bl system_clock_init函數。進入該函數:

可以看到2440是在初始化系統時鐘里關閉看門狗。

下面還有屏蔽中斷的操作:

?

后加

5.接著是運行的是一個函數:看看是定義在那個文件的。

點擊:,然后在Symbol里輸入:lowlevel_init:

會看到出現很多,然后在下面可以看到它們各自的目錄。其實每一個開發板都對應一個lowlevel_init.S:

進入該文件:

5看到系統進入該文件做的第一件事是:初始化系統時鐘:

6.接著初始化串口:

7.對nand進行簡單初始化:

8.接下來的代碼很重要:

由前面的學習知道,當我們開發一個uboot在開發階段,就是在調試uboot的時候,不用燒到NandFlash去運行,可以下載到內存里面去調試運行。這時候就不需要代碼搬移bl0,bl1,bl2的過程。就不需要進行拷貝工作了。所以上面的代碼就是判斷,判斷uboot代碼是在內存運行,還是在NandFlash運行。如果沒有運行在內存當中,就是從NandFlash啟動。就需要對內存進行初始化,就是跳轉到mem_con_init處執行,進行內存初始化。執行完內存初始化之后就要返回了。

返回到:

接著往下執行:

9.判斷是NandFlash啟動還是Nor Flash啟動:

如果是NandFlash啟動這是執行下面的:把代碼從NandFlash拷貝到內存去。

NorFlash這執行下面,把代碼從NorFlash拷貝到內存。

這里講NandFlash啟動,所以跳轉到nand_copy:

?

10,接著是設置堆棧:

?

11.接著清除BSS段:

?

到這里第二階段的代碼就執行完了。

三:

執行完上面,程序跳轉到_start_armboot處執行:

上面的代碼,通過偽指令ldr把_start_armboot的值裝入pc指針,程序就會跳轉到_start_armboot處執行。而此處的地址是start_armboot的地址。就是,程序會跳轉到start_armboot函數處執行。就是把我們的pc指針跳轉到內存去執行了

下面看看start_armboot的地址是不是在內存中。

配置uboot:make smdk2440_config,然后執行make。

然后看到生成的文件:

?

其中,u-boot是elf文件,u-boot.bin是二進制文件。

接下來對u-boot的elf文件,進行反匯編,看看start_armboot函數的地址:

arm-linux-objdump -D -S u-boot >dump

查看:

看到函數的其實地址30009100的地址是在內存里的。所以start.S里的:

實現了從墊腳石跳轉到內存。但是,此時會發現在這里的起始地址被變為了30008000:

在第一階段里,不是說啟動地址是在0嗎?為什么這里是30008000呢?還有就是為什么是這個地址。

?

前面的學習知道,當去鏈接一個程序的時候,程序由多個文件構成,起始地址是由鏈接器腳本決定的。在/home/samba/uboot/Uboot/2440/uboot/board/samsung/smdk2440里的u-boot.lds:

起始地址是0:

這里是0,為什么那里會是30008000呢?我們回到uboot的頂層目錄,打開config.mk:

搜索text_base:

找到:

在這里-T $(LDSCRIPT)就是定義使用鏈接器腳本。后面的-Ttext 是制定代碼段的基地址的。$(TEXT_BASE)。這里有兩個起始地址,然而程序運行的時候以后面的TEXT_BASE的地址為準。它會覆蓋掉LDSCRIPT這個地址。

?

TEXT_BASE是在board/Samsung/smdk2440/config.mk里定義的。最后一行:

?

接下來就是測試驗證一下,把他修改為30005000。然后程序編譯:

Make smdk2440_config->make:

反匯編:

arm-linux-objdump -D -S u-boot >dump

上面的起始地址變了,剛才制定的。

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

那起始地址為什么不是0呢?下圖:

從上圖可以看到,ldr PC,=start_armboot的跳轉,把地址從墊腳石跳轉到內存里。在前面的代碼里,有用到b reset等跳轉指令,為什么這不會跳轉到內存去執行,而是還在墊腳石里呢?

例如:

上面的跳轉,bl lowlevel_init的跳轉地址:

為什么PC指針還是在墊腳石中呢?

?

這就得講兩個詞了。絕對跳轉和相對跳轉

B和bl是相對跳轉。

?

?

?

?

?

Ldr偽指令是絕對跳轉:

?

第三階段:

是從此函數Start_armboot進入的。主要完成的硬件和軟件的初始化,只是一些基礎的初始化。

該函數里有一個for循環:

在for里首先是讓一個指針數組,把里面的函數指針依次調用一次,if里的判斷語句就是函數指針。那么指針數組里有哪些函數指針呢。

?

指針數組:

可以看到里面都是函數指針。這里軟件的初始化就不看了,我們只看硬件的初始化。在這些函數指針里,硬件初始化的有串口初始化。Serial_init。接著是lcd的初始化:

初始化網卡:

初始化led:

接著進入一個主循環:

執行用戶輸入的命令。例如tftp命令。這里是一個死循環。老是等待執行用戶繼續輸入命令。在第一個階段,每個開發板可能有不同的地方,但是在這個地方都是一樣的。就是,在第二階段都是跳到start_armboot處執行代碼。2440的第一階段是在start.S的b reset開始。

轉載于:https://www.cnblogs.com/FORFISH/p/5188716.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/396814.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/396814.shtml
英文地址,請注明出處:http://en.pswp.cn/news/396814.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

linux增加調整虛擬內存

增加虛擬內存:1、檢查當前的分區情況:# free -m2、增加交換分區文件及大小,如果要增加1G大小的交換分區,則命令寫法如下,其中的 bs等于想要的塊大小,count是要增加多少塊,虛擬內存的大小等于bs*count# dd i…

linux練習手冊,Linux操作習題集(1)

動動手實作題:假設你不知道你的主機內部的各項元件資料,請拆開你的主機機殼,並將內部所有的元件拆開,並且依序列出:CPU的廠牌、型號、最高時脈;主記憶體的容量、介面 (DDR/DDR II等);顯示卡的介…

如何使用Redis做MySQL的緩存

應用Redis實現數據的讀寫,同時利用隊列處理器定時將數據寫入mysql。 同時要注意避免沖突,在redis啟動時去mysql讀取所有表鍵值存入redis中,往redis寫數據時,對redis主鍵自增并進行讀取,若mysql更新失敗,則需…

MySQL中CREATE DATABASE和CREATE SCHEMA區別(轉)

在使用MS SQL的時候,一般創建數據庫我們都習慣于使用CREATE DATABASE 來完成,而使用CREATE SCHEMA來創建架構,但是在MySQL中,官方的中文文檔在 CREATE DATABASE 語法一節中寫了一句:也可以使用CREATE SCHEMA。那么CREA…

psychopy 與腦電打碼 eeg

2019獨角獸企業重金招聘Python工程師標準>>> 實驗程序就不放了,這里主要放如何向串口發送打碼的代碼 實際上,給腦電打碼的本質就是向串口發送一個字符,腦電的程序會自動在收到該字符的同時在腦電數據上進行標記。以下代碼打開了一…

deepin linux grub,deepin linux 安裝之后 引導錯誤 出現 grub

deepin 安裝之后 引導錯誤,,, 忙了一晚上 終于解決了 太辛苦了 不過明白了grub的工作原理也不虧,,,, 就是 整個過程滿滿的絕望 (哭具體怎么怎么回事 如下安裝deepin 15.11 安裝完之后不能引導 會卡在grub> 界面以上兩種方式 嘗試了6個小時 都是失敗的 期間出現各種問題 一個…

python怎樣連續輸入兩個數字_python實現輸入數字的連續加減

不用庫,寫了很久,一直出bug,到網上一搜,可以直接輸入之后,eval(str)即可得到結果! eval程序如下: sinput("請輸入要運算的數字") print("The result is{}".format(eval(s))…

修改JAVA代碼,需要重啟Tomcat的原因

準確的說只有修改方法中的內容才不需要重啟,因為tomcat中對于方法的調用是動態的,調用方法的時候,方法的內容才會被加載 新增成員變量,方法,或修改靜態方法和靜態變量、創建新的類 這些都是需要重啟的,因為…

python3輸入輸出_Python3 輸入和輸出

輸出格式美化 Python兩種輸出值的方式: 表達式語句和 print() 函數。(第三種方式是使用文件對象的 write() 方法; 標準輸出文件可以用 sys.stdout 引用。) 如果你希望輸出的形式更加多樣,可以使用 str.format() 函數來格式化輸出值。 如果你希望將輸出的值轉成字符串…

用 vue2 和 webpack 快速建構 NW.js 項目(1)

經過實踐和學習,發現本篇文章部分內容已經過時,請看我的關于 Vue 和 NW.js 的 最新文章 和相關實踐項目 vue-nw-seed 。使用到的技能點 vue2webpackNW.jsNode.js一、前言 先講一下這個項目的由來。我司要新上一個產品,是面向教育領域的一個…

mysql -- 索引的使用

普通索引:用于提升查詢速度唯一索引:用于提升查詢速度,還要求字段值不得重復主鍵索引:唯一性且不為空的索引全文索引:用于大量文本搜索中建立的索引雖然索引有好處,但是凡是都有倆面性,提高效率…

surface pro 7 linux,微軟 Surface Pro、Studio、Laptop 全線更新

今晨,微軟在紐約的秋季新品發布會上,發布了 Surface Pro 6、Laptop 2 以及最頂級的 Studio 2 三款備受期待的 Surface 產品。至此,包括年初的 Surface Book 2 在內,完成了2018 年 Surface 產品線所有升級計劃。當然這場規模不算大…

dremwere怎樣讓多個圖片并列排放_PPT圖片布局不好看?六步教你,看完就會。

我們平時很多場合需要演示講解時,少不了使用PPT。尤其目前白領層人士,項目總結、產品介紹、調研報告…無時無刻不被PPT包圍,又無時無刻不被PPT設計所困惱。誠然設計好看實用的PPT需要高質量素材資源和堅實的文字功底。但在處理美化PPT時&…

ThreadLocal 你到底是個什么鬼

2019獨角獸企業重金招聘Python工程師標準>>> 很多文章都拿它跟同步機制作比較,我覺得這個思路對于理解這個東西完全沒有作用。 ThreadLocal跟synchronize這類東西作比較,是很多文章的套路,我感覺這么比較,就跟比較重載…

SqlServer雙機熱備技術實踐筆記

SqlServer雙機熱備,大體上可以通過發布訂閱,日志傳送,數據庫鏡像來實現。 1,發布--訂閱 是最早最簡單的方案,但需要注意發布的時候,發布進程必須對快照目錄有訪問權限,這個問題可以從“查看快照…

安徽大學計算機教學平臺c語言作業,安徽大學計算機教學部練習題與答案1.pdf

一、計算機基礎知識1.下列敘述中,不是電子計算機特點的是_D____。A.運算速度快 B.計算精度高 C.高度自動化 D.邏輯判斷能力差2.現代電子計算機的本質工作原理是__D___。A.能進行算術運算 B.運算速度高 C.計算精度高 D.存儲并自動執行程序3.微型計算機的型號主要是以…

grep 顯示包含兩個關鍵字_linux三劍客之-grep

一、grep簡介1.介紹全局查找正則表達式并且打印結果行的命令。2.輸入一個文件或者一個標準輸入(stdin),或者是一個“-”連字符()。3.輸出打印在屏幕上4.grep家族擴展命令egrep、fgrep二、 Grep命令的應用1.命令格式grep [選項] 模式 [文件…]例如:grep root /etc/pa…

Python裝飾器的實現原理

Python中的裝飾器是通過利用了函數特性的閉包實現的,所以在說裝飾器之前,我們需要先了解函數特性,以及閉包是怎么利用了函數特性的。 1.函數特性 Python中的函數特性總的來說有四點: 1.函數作為變量傳遞 def add(x):return x 1a add 2.函數…

c語言注釋說明被計算機編譯系統忽略,C語言程序設計(陳艷 2019-2020-2)-中國大學mooc-題庫零氪...

第1章 C語言概述第1講 C語言概述隨堂測驗1、程序 #include void main() { printf("Hello, world!\n"); } 經過編譯運行會在顯示器上輸出 Hello, world! 如果希望輸出:Nice to meet you. 則應使用Nice to meet you.替換( )。A、voidB、mainC、p…

React文檔(五)組件和props

組件可以讓你將UI分割成獨立的,可復用的模塊,然后考慮將每個模塊彼此隔離。從概念上理解,組件就像js中的函數。他們接受隨意的輸入(被稱為props)然后返回React元素來描述屏幕上應該出現什么。 函數式和類式組件 定義一…