Linuxプログラミング入門--正点原子Linux駆動開発ガイドライン学習2021 W 26
9030 ワード
十一、U-Boot起動プロセスの詳細
(1)リンクスクリプトu-boot.lds詳細
コンパイルが完了するとubootルートディレクトリの下でu-bootが生成される.ldsファイル、このファイルからU-boot起動プロセスを分析します.
ファイルでarch/arm/lib/vectors.Sでは、個別のセグメント
(2)Cortex-A 7割り込みシステムの詳細 GICコントローラ一覧 ここでCortex-A 7が中断した知識を補足します.そうしないと、後の分析は少し難しいです.Cortex-A 7にも割り込みベクトルテーブルがあり、割り込みベクトルテーブルもコードの先頭にあります.CortexA 7カーネルには8つの異常割り込みがあり、この8つの異常割り込みの割り込みベクトル表は以下の表の通りである.
ベクトルアドレス
ターミナルタイプ
割り込みモード
紹介する
0x00
複数回中断(RSET)
特権モード(SVC)
CPUリセット後はリセット割り込みに入ります.リセット割り込みサービス関数では、SPポインタの初期化、DDRの初期化など、初期化作業を行うことができます.
0x04
未定義命令割り込み(Undefined Instruction)
命令中止モードが定義されていません(Undef)
命令が認識されないと、この割り込みが発生します.
0x08
ソフトブレーク(Software Interrupt,SWI)
特権モード(SVC)
SWI命令による割り込み,Linuxのシステム呼び出しはSWI命令によりソフト割り込みを起こし,ソフト割り込みによりカーネル空間に陥る.
0x0C
命令プリフェッチ中断(Prefetch Abort)
中止モード
プリフェッチ命令のエラー時にこの割り込みが発生します.
0x10
データアクセス中断(Data Abort)
中止モード
この割り込みは、データへのアクセスエラー時に発生します.
0x14
未使用(Not Used)
未使用
ユニット4
0x18
IRQ割込み(IRQ Interrupt)
外部割り込みモード(IRQ)
チップ内部の周辺機器の割り込みは、この割り込みを引き起こす.
0x1C
FIQ割込み(FIQ Interrupt)
クイックブレークモード(FIQ)
割り込みをすばやく処理すれば、この割り込みを使用できます.
GICはARM社がCortex-A/Rカーネルに提供する割り込みコントローラであり、Cortex-MカーネルのNVICに似ている.現在GICには4つのバージョンがある:V 1~V 4、V 1は最も古いバージョンで、すでに廃棄されている.V 2~V 4は現在大量に使用されている.GIC V 2はARMv 7-Aアーキテクチャに使用され、I.MX 6 Uが使用する.ARMはGIC V 2に対してGIC 400という割り込みコントローラIPコアを開発した.GICが外部割り込み信号を受信するとARMカーネルに報告されるが、ARMカーネルは、VFIQ(仮想高速割り込み)、VIRQ(仮想外部割り込み)、FIQ、およびIRQの4つの信号のみをGICに提供する.割り込みID GICは多くの割り込みソースを3つに分類します.
割り込みソースはたくさんありますが、これらの異なる割り込みソースを区別するためには、割り込みIDである一意のIDを割り当てる必要があります.各CPUは最大1020個の割り込みIDをサポートし、割り込みID番号はID 0~ID 1019である.ID 0~ID 15:この16個のIDはSGIに割り当てられる.ID 16~ID 31:この16個のIDはPPIに割り当てられる.ID 32~ID 1019:この988個のIDはSPIに割り当てられており、GPIO割込み、シリアルポート割込みなどの外部割込みのように、あるIDがどの割込みに対応するかを具体的には半導体メーカーが実際の状況に応じて定義している. GIC論理ブロック GICアーキテクチャは2つの論理ブロックに分けられる:DistributorとCPU Interface、すなわち配布器側とCPUインタフェース側.Distributor(ディストリビュータ側):この論理ブロックは、各割り込みイベントの配布問題、すなわち、割り込みイベントがどのCPU Interfaceに送信されるべきかを処理する.配布器はすべての割り込みソースを収集し、各割り込みの優先度を制御することができ、常に優先度が最も高い割り込みイベントをCPUインタフェース側に送信する.配布器側が行う主な仕事は以下の通りである:1、グローバル中断使能制御.②、各割り込みのイネーブル又はクローズを制御する.③、割り込みごとの優先度を設定する.④、割り込みごとのターゲットプロセッサリストを設定します.⑤、各外部割り込みのトリガモードを設定する:レベルトリガまたはエッジトリガ.⑥各割り込みがグループ0に属するかグループ1に属するかを設定します.CPU Interface(CPUインタフェース端子):CPUインタフェース端子は名前を聞くとCPU Coreに接続されていることがわかり、各CPU CoreはGICで対応するCPU Interfaceを見つけることができる.CPUインタフェース端子は配布器とCPU Coreとの架け橋であり、CPUインタフェース端子は主に以下のように動作する:1、CPU Coreに送信された割り込み要求信号をオフまたはオフにする.②、応答が途切れる.③、割り込み処理完了を通知する.④、優先マスクを設定し、マスクによってCPU Coreに報告する必要のない割り込みを設定する.⑤、プリエンプトポリシーを定義する.⑥複数の割り込みが来た場合、優先度が最も高い割り込み通知をCPU Coreに選択する.
(3)U-Boot起動フロー詳細 reset関数ソースコード詳細 前述arch/arm/lib/vectors.S割り込みベクトルテーブルのreset,reset関数はarch/arm/cpu/armv 7/start.Sの中.35行でresetの定義を見て、ここでまたsave_にジャンプします.boot_params.
100行でsave_が定義されていますboot_params、ここでまたsaveにジャンプboot_params_ret .
38行でsave_が定義されていますboot_params_ret
下に進み続け、
さらに下に進むと、
ここではcpu_を重点的に見ますinit_crit関数は259行で、
reset関数が最終的にlowlevelにジャンプすることがわかります.initと_mainという2つの関数です.後で分析します.
(1)リンクスクリプトu-boot.lds詳細
コンパイルが完了するとubootルートディレクトリの下でu-bootが生成される.ldsファイル、このファイルからU-boot起動プロセスを分析します.
/*
1. 3 : _start, _start arch/arm/lib/vectors.S
2. __image_copy_start u-boot-spl.lds , .text
*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x00000000;
. = ALIGN(4);
.text :
{
*(.__image_copy_start)
*(.vectors)
arch/arm/cpu/armv7/start.o (.text*)
*(.text*)
}
. = ALIGN(4);
.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
. = ALIGN(4);
.data : {
*(.data*)
}
. = ALIGN(4);
. = .;
. = ALIGN(4);
.u_boot_list : {
KEEP(*(SORT(.u_boot_list*)));
}
. = ALIGN(4);
.image_copy_end :
{
*(.__image_copy_end)
}
.rel_dyn_start :
{
*(.__rel_dyn_start)
}
.rel.dyn : {
*(.rel*)
}
.rel_dyn_end :
{
*(.__rel_dyn_end)
}
.end :
{
*(.__end)
}
_image_binary_end = .;
. = ALIGN(4096);
.mmutable : {
*(.mmutable)
}
.bss_start __rel_dyn_start (OVERLAY) : {
KEEP(*(.__bss_start));
__bss_base = .;
}
.bss __bss_base (OVERLAY) : {
*(.bss*)
. = ALIGN(4);
__bss_limit = .;
}
.bss_end __bss_limit (OVERLAY) : {
KEEP(*(.__bss_end));
}
.dynsym _image_binary_end : { *(.dynsym) }
.dynbss : { *(.dynbss) }
.dynstr : { *(.dynstr*) }
.dynamic : { *(.dynamic*) }
.plt : { *(.plt*) }
.interp : { *(.interp*) }
.gnu.hash : { *(.gnu.hash) }
.gnu : { *(.gnu*) }
.ARM.exidx : { *(.ARM.exidx*) }
.gnu.linkonce.armexidx : { *(.gnu.linkonce.armexidx.*) }
}
ファイルでarch/arm/lib/vectors.Sでは、個別のセグメント
.section ".vectors", "ax"
が定義されていることがわかる.startの後ろには割り込みベクトルテーブルがあります.#include
/*
*************************************************************************
*
* Symbol _start is referenced elsewhere, so make it global
*
*************************************************************************
*/
.globl _start
/*
*************************************************************************
*
* Vectors have their own section so linker script can map them easily
*
*************************************************************************
*/
.section ".vectors", "ax"
/*
*************************************************************************
*
* Exception vectors as described in ARM reference manuals
*
* Uses indirect branch to allow reaching handlers anywhere in memory.
*
*************************************************************************
*/
_start:
#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG
.word CONFIG_SYS_DV_NOR_BOOT_CFG
#endif
b reset
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
(2)Cortex-A 7割り込みシステムの詳細
ベクトルアドレス
ターミナルタイプ
割り込みモード
紹介する
0x00
複数回中断(RSET)
特権モード(SVC)
CPUリセット後はリセット割り込みに入ります.リセット割り込みサービス関数では、SPポインタの初期化、DDRの初期化など、初期化作業を行うことができます.
0x04
未定義命令割り込み(Undefined Instruction)
命令中止モードが定義されていません(Undef)
命令が認識されないと、この割り込みが発生します.
0x08
ソフトブレーク(Software Interrupt,SWI)
特権モード(SVC)
SWI命令による割り込み,Linuxのシステム呼び出しはSWI命令によりソフト割り込みを起こし,ソフト割り込みによりカーネル空間に陥る.
0x0C
命令プリフェッチ中断(Prefetch Abort)
中止モード
プリフェッチ命令のエラー時にこの割り込みが発生します.
0x10
データアクセス中断(Data Abort)
中止モード
この割り込みは、データへのアクセスエラー時に発生します.
0x14
未使用(Not Used)
未使用
ユニット4
0x18
IRQ割込み(IRQ Interrupt)
外部割り込みモード(IRQ)
チップ内部の周辺機器の割り込みは、この割り込みを引き起こす.
0x1C
FIQ割込み(FIQ Interrupt)
クイックブレークモード(FIQ)
割り込みをすばやく処理すれば、この割り込みを使用できます.
GICはARM社がCortex-A/Rカーネルに提供する割り込みコントローラであり、Cortex-MカーネルのNVICに似ている.現在GICには4つのバージョンがある:V 1~V 4、V 1は最も古いバージョンで、すでに廃棄されている.V 2~V 4は現在大量に使用されている.GIC V 2はARMv 7-Aアーキテクチャに使用され、I.MX 6 Uが使用する.ARMはGIC V 2に対してGIC 400という割り込みコントローラIPコアを開発した.GICが外部割り込み信号を受信するとARMカーネルに報告されるが、ARMカーネルは、VFIQ(仮想高速割り込み)、VIRQ(仮想外部割り込み)、FIQ、およびIRQの4つの信号のみをGICに提供する.
① SPI(Shared Peripheral Interrupt), , , Core , , SPI ( ! SPI ) 。 、 , Core , Core。
② PPI(Private Peripheral Interrupt), , GIC , 。 , 。
③ SGI(Software-generated Interrupt), , , GICD_SGIR , SGI 。
割り込みソースはたくさんありますが、これらの異なる割り込みソースを区別するためには、割り込みIDである一意のIDを割り当てる必要があります.各CPUは最大1020個の割り込みIDをサポートし、割り込みID番号はID 0~ID 1019である.ID 0~ID 15:この16個のIDはSGIに割り当てられる.ID 16~ID 31:この16個のIDはPPIに割り当てられる.ID 32~ID 1019:この988個のIDはSPIに割り当てられており、GPIO割込み、シリアルポート割込みなどの外部割込みのように、あるIDがどの割込みに対応するかを具体的には半導体メーカーが実際の状況に応じて定義している.
(3)U-Boot起動フロー詳細
.globl reset
.globl save_boot_params_ret
reset:
/* Allow the board to save important registers */
b save_boot_params
100行でsave_が定義されていますboot_params、ここでまたsaveにジャンプboot_params_ret .
/*************************************************************************
*
* void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3)
* __attribute__((weak));
*
* Stack pointer is not yet initialized at this moment
* Don't save anything to stack even if compiled with -O0
*
*************************************************************************/
ENTRY(save_boot_params)
b save_boot_params_ret @ back to my caller
38行でsave_が定義されていますboot_params_ret
save_boot_params_ret:
/*
* disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,
* except if in HYP mode already
*/
mrs r0, cpsr @ cpsr r0
and r1, r0, #0x1f @ mask mode bits
teq r1, #0x1a @ test for HYP mode
bicne r0, r0, #0x1f @ clear all mode bits r1 0X1A , r0
orrne r0, r0, #0x13 @ set SVC(Supervisor) mode r1 0X1A , r0 #0x13
orr r0, r0, #0xc0 @ disable FIQ and IRQ
msr cpsr,r0
下に進み続け、
/*
* Setup vector:
* (OMAP4 spl TEXT_BASE is not 32 byte aligned.
* Continue to use ROM code vector only in OMAP4 spl)
*/
#if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD))
/* Set V=0 in CP15 SCTLR register - for VBAR to point to vector */
mrc p15, 0, r0, c1, c0, 0 @ Read CP15 SCTLR Register CP15 c1 r0
bic r0, #CR_V @ V = 0 CR_V = (1 << 13), SCTLR bit13
mcr p15, 0, r0, c1, c0, 0 @ Write CP15 SCTLR Register r0 SCTLR
/* Set vector address in CP15 VBAR register */
ldr r0, =_start @ _start uboot , 0X87800000
mcr p15, 0, r0, c12, c0, 0 @Set VBAR r0 ( ) CP15 c12 , VBAR 。
#endif
さらに下に進むと、
/* the mask ROM code should have PLL and others stable */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_cp15 // 105 , CP15 , MMU
bl cpu_init_crit
#endif
bl _main
ここではcpu_を重点的に見ますinit_crit関数は259行で、
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
/*************************************************************************
*
* CPU_init_critical registers
*
* setup important registers
* setup memory timing
*
*************************************************************************/
ENTRY(cpu_init_crit)
/*
* Jump to board specific initialization...
* The Mask ROM will have already initialized
* basic memory. Go here to bump up clock rate and handle
* wake up conditions.
*/
b lowlevel_init @ go setup pll,mux,memory
ENDPROC(cpu_init_crit)
#endif
reset関数が最終的にlowlevelにジャンプすることがわかります.initと_mainという2つの関数です.後で分析します.