1、嵌入式Linux軟件結構與分佈在一般情況下嵌入式Linux系統中的軟件主要分爲以下及部分:
(1)引導加載程序:其中包括內部ROM中的固化啓動代碼(彙編代碼)和Boot Loader(C代碼)兩部分。而這個內部固化ROM是廠家在芯片生產時候固化的,作用基本上是引導Boot Loader。有的芯片比較複雜,比如Omap3,他在flash中沒有代碼的時候有許多啓動方式:USB、UART或以太網等等。而S3C24x0則很簡單,只有Norboot和Nandboot。比如三星的S3C24X0系列,它的bootROM直接跳到U-boot中執行,首先由bootROM將U-boot的前4KB拷貝到處理器ISRAM,接着在U-boot的前4KB中必須保證要完成的兩項主要工作:初始化DDR,nand和nand控制器,接着將U-boot剩餘的code拷貝到SDRAM中,然後跳到SDRAM的對應地址上去繼續跑U-boot。總的來說,引導程序是初始化軟硬件,爲操作系統運行做準備。
(2)Linux kernel 和drivers。
(3)文件系統。包括根文件系統和建立於Flash內存設備之上的文件系統(EXT4、UBI、CRAMFS等等)。它是提供管理系統的各種配置文件以及系統執行用戶應用程序的良好運行環境的載體。
(4)應用程序。用戶自定義的應用程序,存放於文件系統之中。
在Flash 存儲器中,他們的 一般分佈如下:
但是以上只是大部分情況下的分佈,也有一些可能根文件系統是initramfs,被一起壓縮到了內核映像裏,或者沒有Bootloader參數區,等等。
由上可知,Loader大概可分爲兩部分:第一部分,彙編代碼。第二部分,C代碼。
以3288 U-Boot代碼爲例:
第一部分:
第一條指令從arch/arm/cpu/armv7/start.S開始(注意紅色字體關鍵語句及註釋):
.globl reset //硬件服務操作
reset:
/*
* check loader tag
*/
#ifdef CONFIG_ROCKCHIP
ldr r0, =__loader_tag //講地址
ldr r1, [r0]
ldr r0, =LoaderTagCheck
ldr r0, [r0]
cmp r1, r0 //比較兩個地址的內容是否一致。
movne pc, r14 //將r14(LR:鏈接寄存器,保存被調用子函數的返回地址)內容複製到pc寄存器(r15:程序計數器,保存將要 執行的指令地址)
#endif
bl save_boot_params //直接返回,沒有做任何事情
/*
* disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,
* except if in HYP mode already,關中斷,設置CPU到SVC(超級保護)模式
*/
mrs r0, cpsr
and r1, r0, #0x1f @ mask mode bits
teq r1, #0x1a @ test for HYP mode
bicne r0, r0, #0x1f @ clear all mode bits
orrne r0, r0, #0x13 @ set SVC mode
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 SCTRL register - for VBAR to point to vector */
mrc p15, 0, r0, c1, c0, 0 @ Read CP15 SCTRL Register
bic r0, #CR_V @ V = 0
mcr p15, 0, r0, c1, c0, 0 @ Write CP15 SCTRL Register
/* Set vector address in CP15 VBAR register */
#ifdef CONFIG_ROCKCHIP//設置寄存器
ldr r0, =_vector
#else
ldr r0, =_start
#endif
mcr p15, 0, r0, c12, c0, 0 @Set VBAR
#endif
/* the mask ROM code should have PLL and others stable */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_cp15
bl cpu_init_crit
#endif
bl _main
cpu_init_cp15主要是CP15協處理器初始化操作,disable cache和MMU
cpu_init_crit初始化ARM關鍵寄存器,刷新cache和TLB,關閉MMU,初始化時鐘。Boot初始化的時候,程序看到的是物理地址,無需MMU
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//直接跳到板級文件實現
lowlevel_init的實現在arch/arm/cpu/armv7/rk32xx/lowlevel_init.S中
ENTRY(lowlevel_init)
/*
* Setup a temporary stack
*/
ldr sp, =CONFIG_SYS_INIT_SP_ADDR
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
#ifdef CONFIG_SPL_BUILD
ldr r8, =gdata
#else
sub sp, #GD_SIZE
bic sp, sp, #7
mov r8, sp
#endif
#ifndef CONFIG_SYS_DCACHE_OFF
/*
* TTBCR default setting 0.
*/
mov r0, #0
mcr p15, 0, r0, c2, c0, 2 @ TTBCR (Translation Table Base Control Register)
#endif
/*
* Save the old lr(passed in ip) and the current lr to stack
*/
push {ip, lr}
bl rkclk_set_pll //初始化時鐘
pop {ip, pc}
ENDPROC(lowlevel_init)
然後跳到_main()函數arch/arm/lib/crt0.S:_main()函數主要初始化C運行環境,然後跳到board_init_f,進行板級前端初始化操作