uboot流程——uboot启动流程
[uboot] (第五章)uboot流程——uboot啟動流程
2016年11月07日 20:12:07閱讀數:2230以下例子都以project X項目tiny210(s5pv210平臺,armv7架構)為例
[uboot] uboot流程系列:?
[project X] tiny210(s5pv210)上電啟動流程(BL0-BL2)?
[project X] tiny210(s5pv210)從存儲設備加載代碼到DDR?
[uboot] (第一章)uboot流程——概述?
[uboot] (第二章)uboot流程——uboot-spl編譯流程?
[uboot] (第三章)uboot流程——uboot-spl代碼流程?
[uboot] (第四章)uboot流程——uboot編譯流程?
[uboot] (番外篇)global_data介紹?
[uboot] (番外篇)uboot relocation介紹
建議先看《[project X] tiny210(s5pv210)上電啟動流程(BL0-BL2)》,根據例子了解一下上電之后的BL0\BL1\BL2階段,以及各個階段的運行位置,功能。?
建議可以和《[uboot] (番外篇)global_data介紹》和《[uboot] (番外篇)uboot relocation介紹》結合起來看。
=================================================================================
一、uboot說明
1、uboot要做的事情
CPU初始剛上電的狀態。需要小心的設置好很多狀態,包括cpu狀態、中斷狀態、MMU狀態等等。其次,就是要根據硬件資源進行板級的初始化,代碼重定向等等。最后,就是進入命令行狀態,等待處理命令。?
在armv7架構的uboot,主要需要做如下事情
arch級的初始化
- 關閉中斷,設置svc模式
- 禁用MMU、TLB
- 關鍵寄存器的設置,包括時鐘、看門狗的寄存器
板級的初始化
- 堆棧環境的設置
- 代碼重定向之前的板級初始化,包括串口、定時器、環境變量、I2C\SPI等等的初始化
- 進行代碼重定向
- 代碼重定向之后的板級初始化,包括板級代碼中定義的初始化操作、emmc、nand flash、網絡、中斷等等的初始化。
- 進入命令行狀態,等待終端輸入命令以及對命令進行處理
上述工作,也就是uboot流程的核心。
2、疑問
在前面的文章中雖然已經說明了,在spl的階段中已經對arch級進行了初始化了,為什么uboot里面還要對arch再初始化一遍??
回答:spl對于啟動uboot來說并不是必須的,在某些情況下,上電之后uboot可能在ROM上或者flash上開始執行而并沒有使用spl。這些都是取決于平臺的啟動機制。因此uboot并不會考慮spl是否已經對arch進行了初始化操作,uboot會完整的做一遍初始化動作,以保證cpu處于所要求的狀態下。和spl在啟動過程的差異在哪里??
回答:以tiny210而言,前期arch的初始化流程基本上是一致的,出現本質區別的是在board_init_f開始的。- spl的board_init_f是由board自己實現相應的功能,例如tiny210則是在board/samsung/tiny210/board.c中。其主要實現了復制uboot到ddr中,并且跳轉到uboot的對應位置上。一般spl在這里就可以完成自己的工作了。
- uboot的board_init_f是在common下實現的,其主要實現uboot relocate前的板級初始化以及relocate的區域規劃,其還需要往下走其他初始化流程。
3、代碼入口
project-X/u-boot/arch/arm/cpu/u-boot.lds
ENTRY(_start)- 1
所以uboot-spl的代碼入口函數是_start?
對應于路徑project-X/u-boot/arch/arm/lib/vector.S的_start,后續就是從這個函數開始分析。
二、代碼整體流程
1、首先看一下主枝干的流程(包含了arch級的初始化)
在arch級初始化是和spl完全一致的?
_start———–>reset————–>關閉中斷?
………………………………|?
………………………………———->cpu_init_cp15———–>關閉MMU,TLB?
………………………………|?
………………………………———->cpu_init_crit————->lowlevel_init————->關鍵寄存器的配置和初始化?
………………………………|?
………………………………———->_main————–>進入板級初始化,具體看下面
2、板級初始化的流程
_main————–>board_init_f_alloc_reserve —————>堆棧、GD、early malloc空間的分配?
…………|?
…………————->board_init_f_init_reserve —————>堆棧、GD、early malloc空間的初始化?
…………|?
…………————->board_init_f —————>uboot relocate前的板級初始化以及relocate的區域規劃?
…………|?
…………————->relocate_code、relocate_vectors —————>進行uboot和異常中斷向量表的重定向?
…………|?
…………————->舊堆棧的清空?
…………|?
…………————->board_init_r —————>uboot relocate后的板級初始化?
…………|?
…………————->run_main_loop —————>進入命令行狀態,等待終端輸入命令以及對命令進行處理
三、arch級初始化代碼分析
1、_start
上述已經說明了_start是整個uboot的入口,其代碼如下:?
arch/arm/lib/vector.S
- 1
- 2
- 3
- 4
- 5
會跳轉到reset中。
2、reset
建議先參考[kernel 啟動流程] (第二章)第一階段之——設置SVC、關閉中斷,了解一下為什么要設置SVC、關閉中斷以及如何操作。
代碼如下:?
arch/arm/cpu/armv7/start.S
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
3、cpu_init_cp15
建議先參考[kernel 啟動流程] (第六章)第一階段之——打開MMU兩篇文章的分析。?
cpu_init_cp15主要用于對cp15協處理器進行初始化,其主要目的就是關閉其MMU和TLB。?
代碼如下(去掉無關部分的代碼):?
arch/arm/cpu/armv7/start.S
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
4、cpu_init_crit
cpu_init_crit,進行一些關鍵寄存器的初始化動。其代碼核心就是lowlevel_init,如下?
arch/arm/cpu/armv7/start.S
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
所以說lowlevel_init就是這個函數的核心。?
lowlevel_init一般是由板級代碼自己實現的。但是對于某些平臺來說,也可以使用通用的lowlevel_init,其定義在arch/arm/cpu/lowlevel_init.S中?
以tiny210為例,在移植tiny210的過程中,就需要在board/samsung/tiny210下,也就是板級目錄下面創建lowlevel_init.S,在內部實現lowlevel_init。(其實只要實現了lowlevel_init了就好,沒必要說在哪里是實現,但是通常規范都是創建了lowlevel_init.S來專門實現lowlevel_init函數)。
在lowlevel_init中,我們要實現如下:
- 檢查一些復位狀態
- 關閉看門狗
- 系統時鐘的初始化
- 內存、DDR的初始化
- 串口初始化(可選)
- Nand flash的初始化
下面以tiny210的lowlevel_init為例(這里說明一下,當時移植tiny210的時候,是直接把kangear的這個lowlevel_init.S文件拿過來用的)?
這部分代碼和平臺相關性很強,簡單介紹一下即可?
board/samsung/tiny210/lowlevel_init.S
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
當串口中打印出‘OK’的字符的時候,說明lowlevel_init已經執行完成。
三、板級初始化代碼分析
1、_main
板級初始化代碼的入口就是_main。從這里開始分析。?
建議可以和《[uboot] (番外篇)global_data介紹》和《[uboot] (番外篇)uboot relocation介紹》結合起來看。?
代碼如下,去除無關代碼部分?
arch/arm/lib/crt0.S
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
通過上述,有兩個很重要的初始化函數,board_init_f和board_init_r,后續繼續說明。
2、board_init_f
代碼如下:?
common/board_f.c
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
打開DEBUG宏之后,可以通過log觀察哪些init函數被調用,如下log:
uboot log中有如下log: initcall: 23e005a4 根據u-boot.map可以發現對應.text.print_cpuinfo0x23e005a4 0x8 arch/arm/cpu/armv7/built-in.o0x23e005a4 print_cpuinfo 也就是說print_cpuinfo被initcall調用了。- 1
- 2
- 3
- 4
- 5
- 6
- 7
所以uboot relocate之前的板級初始化的核心就是init_sequence_f中定義的函數了。?
如下,這里只做簡單的說明,需要的時候再具體分析:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
注意,必須保證上述的函數都正確地返回0值,否則會導致hang。
3、board_init_r
代碼如下:?
common/board_r.c
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
所以uboot relocate之前的板級初始化的核心就是init_sequence_r中定義的函數了。?
如下,這里只做簡單的說明,需要的時候再具體分析:?
common/board_r.c
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
最終,uboot運行到了run_main_loop,并且在run_main_loop進入命令行狀態,等待終端輸入命令以及對命令進行處理。?
到此,uboot流程也就完成了,后續會專門說明uboot的run_main_loop是怎么運行的。
總結
以上是生活随笔為你收集整理的uboot流程——uboot启动流程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 6-uboot relocation介绍
- 下一篇: uboot流程——命令行模式以及命令处理