欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
關(guān)于嵌入式系統的啟動(dòng)

一篇很好的講解嵌入式linux啟動(dòng)的文章


嵌入式Linux啟動(dòng)分為兩個(gè)部分,系統引導與Linux啟動(dòng)。系統引導將完成Linux裝入內存前,初始化CPU和相關(guān)IO設備,并將Linux調入內存的工作。系統引導主要由BootLoader實(shí)現。在BootLoaderLinux內核調入內存之后,將權力交給LinuxKernel,進(jìn)入Linux的啟動(dòng)部分。以下詳細分析啟動(dòng)的過(guò)程與使用的文件。

一、系統引導與BootLoader
        BootLoader
因嵌入式系統的不同與PC機有很大不同,這里將以Hyper250(Inter Xscale GDPXA250)的啟動(dòng)為例來(lái)分析。由于沒(méi)有BIOS驅動(dòng)主板,EnbeddedOS必須由bootloader驅動(dòng)所有的硬件,并完成硬件的初始化工作。
       
所有的初始化文件在hyper250/Bootloader目錄下。
       
       
首先分析開(kāi)機運行的分件:
                hyper250/Bootloader/X-Hyper250R1.1-Boot/src/start_xscale.S
       
文件包含兩個(gè)庫文件:
                hyper250/Bootloader/X-Hyper250R1.1-Boot/src/include/config.h
                hyper250/Bootloader/X-Hyper250R1.1-Boot/src/include/start_xscale.h
       
文件config.h主要完成系統各硬件的宏定義與設定,xscale.h主要完成對系統芯片的及系統操作的設定。

       
以下分析config.h文件:
        (1)
存儲總線(xiàn)設備的宏定義:定義Flash的大小、字長(cháng)等信息,定義SRAM的基址、大小和塊大小。
        (2)
動(dòng)態(tài)內存設定:定義DRAM的大小、基址。
        (3)
軟件包信息:包名稱(chēng)、版本號。
        (4)
設定BOOT LOADER的位置:在DRAMSRAM的最大值、DRAM裝入位置、棧的基址。
        (5)
設定kernel的位置:在DRAMSRAM的基址、KERNEL的最大值、KERNEL中塊的數量。
        (6)
設定文件系統的位置:根目錄在DRAMSRAM的基址、文件系統的最大值、文件系統中塊的數量。
        (7)
設定LOADER程序:LOADER程序的靜態(tài)內存基址、LOADER程序的最大值、塊的數量。
        (8)
網(wǎng)絡(luò )設定
       
       
以下分析start_xcalse.h文件:
        (1)
定義內存基址(A0000000)
        (2)
定義中斷基址(40D00000)和中斷保護棧的偏移量
        (3)
定義時(shí)鐘管理基址(41300000)和寄存器偏移及其初始值
        (4)
定義GPIO接口寄存器基址(40E00000)及各寄存器的偏移
        (5)
定義GPIO接口各寄存器的初始值
        (6)
定義內存控制寄存器基址(48000000)和各寄存器的偏移
        (7)
定義內存控制寄存器的初始值
        (8)
定義電源管理寄存器的參數
        (9)
定義FFUART寄存器的基址(40100000)和各寄存器的偏移
        (10)
定義FFUART各寄存器的初始值
       
       
以下分析start_xcalse.S文件:
        (1)
設定中斷基址(40D00000),完成中斷保護棧的初始化
        (2)
初始化GPIO接口
        (3)
初始化內存SDRAM
        (4)
BootloaderFlash拷貝到SDRAM
        (5)
裝入Linux內核鏡像,將內核從Flash(000C 0000)裝入SDRAM(A0008000).
        (6)
設定保護棧
        (7)
調用main.c的主函數c_main()       
       
       
以上start_xcalse.S通過(guò)APCS的編程標準書(shū)寫(xiě)的匯編文件初始化了系統相關(guān)的硬件,并且完成了BootLoader的裝入內存和Linux內核的裝入,最后將權力轉交給main.c。
       
以下將分析main.c文件:
                hyper250/Bootloader/X-Hyper250R1.1-Boot/src/main.c
       
以及兩個(gè)庫文件
                hyper250/Bootloader/X-Hyper250R1.1-Boot/src/include/main.h
                hyper250/Bootloader/X-Hyper250R1.1-Boot/src/include/scc.h

#2  

二、Linux啟動(dòng)過(guò)程分析

        1.Makefile
分析:
       
在分析arch/arm/boot/compressed目錄下的文件的時(shí)候,對于Makefile的分析是很重要的,因為內核將在這個(gè)目錄相產(chǎn)生。這里主要工作是對內核的壓縮和解壓工作。本目錄在編譯完成后將產(chǎn)生vmlinux、head.o、misc.o、head-xscale.o、piggy.o這幾個(gè)文件。其中vmlinux沒(méi)有壓縮過(guò)的內核。head.o是內核的頭部文件,負責初始設置。misc.o將主要負責內核的解壓工作,它在head.o之后。head-xscale.o文件主要針對Xscale的初始化,將在鏈接時(shí)與head.o合并。piggy.o是一個(gè)中間文件,其實(shí)是一個(gè)壓縮的內核,只不過(guò)沒(méi)有和初始化文件及解壓文件鏈接而已。
       
        2.Decompress
分析:
       
BootLoader完成系統的引導以后并將Linux內核調入內存之后,調用bootLinux(),這個(gè)函數將跳轉到kernel的起始位置。如果kernel沒(méi)有壓縮,就可以啟動(dòng)了。如果kernel壓縮過(guò),則要進(jìn)行解壓,在壓縮過(guò)的kernel頭部有解壓程序。壓縮過(guò)得kernel入口第一個(gè)文件源碼位置在arch/arm/boot/compressed/head.S。它將調用函數decompress_kernel(),這個(gè)函數在文件arch/arm/boot/compressed/misc.c中,decompress_kernel()又調用proc_decomp_setup(),arch_decomp_setup()進(jìn)行設置,然后使用在打印出信息“Uncompressing Linux...”后,調用gunzip()。將內核放于指定的位置。
       
啟動(dòng)首先運行的文件有:
                arch/arm/boot/compressed/head.S
                arch/arm/boot/compressed/head-xscale.S
                arch/arm/boot/compressed/misc.c
       
這些文件主要用于解壓內核和以及啟動(dòng)內核映象。一旦內核啟動(dòng),則這些文件所占內存空間將被釋放。而且,一旦系統通過(guò)reset重起,當BootLoader將壓縮過(guò)的內核放入內存中,首先執行的必然是這些代碼。
       
       
以下分析head.S文件:
        (1)
對于各種Arm CPUDEBUG輸出設定,通過(guò)定義宏來(lái)統一操作。
        (2)
設置kernel開(kāi)始和結束地址,保存architecture ID。
        (3)
如果在ARM2以上的CPU中,用的是普通用戶(hù)模式,則升到超級用戶(hù)模式,然后關(guān)中斷。
        (4)
分析LC0結構delta offset,判斷是否需要重載內核地址(r0存入偏移量,判斷r0是否為零)。
       
這里是否需要重載內核地址,我以為主要分析arch/arm/boot/Makefile、arch/arm/boot/compressed/Makefilearch/arm/boot/compressed/vmlinux.lds.in三個(gè)文件,主要看vmlinux.lds.in鏈接文件的主要段的位置,LOAD_ADDR(_load_addr)0xA0008000,而對于TEXT_START(_text、_start)的位置只設為0,BSS_START(__bss_start)ALIGN(4)。對于這樣的結果依賴(lài)于,對內核解壓的運行方式,也就是說(shuō),內核解壓前是在內存(RAM)中還是在FLASH上,因為這里,我們的BOOTLOADER將壓縮內核(zImage)移到了RAM0xA0008000位置,我們的壓縮內核是在內存(RAM)0xA0008000地址開(kāi)始順序排列,因此我們的r0獲得的偏移量是載入地址(0xA0008000)。接下來(lái)的工作是要把內核鏡像的相對地址轉化為內存的物理地址,即重載內核地址。
        (5)
需要重載內核地址,將r0的偏移量加到BSS regionGOT table中。
        (6)
清空bss堆??臻gr2r3。
        (7)
建立C程序運行需要的緩存,并賦于64K的??臻g。
        (8)
這時(shí)r2是緩存的結束地址,r4kernel的最后執行地址,r5kernel境象文件的開(kāi)始地址。檢查是否地址有沖突。
               
r5等于r2,使decompress后的kernel地址就在64K的棧之后。
        (9)
調用文件misc.c的函數decompress_kernel(),解壓內核于緩存結束的地方(r2地址之后)。此時(shí)各寄存器值有如下變化:
                r0
為解壓后kernel的大小
                r4
kernel執行時(shí)的地址
                r5
為解壓后kernel的起始地址
                r6
CPU類(lèi)型值(processor ID)
                r7
為系統類(lèi)型值(architecture ID)
        (10)
reloc_start代碼拷貝之kernel之后(r5+r0之后),首先清除緩存,而后執行reloc_start。
        (11)reloc_start
r5開(kāi)始的kernel重載于r4地址處。
        (12)
清除cache內容,關(guān)閉cache,將r7architecture ID賦于r1,執行r4開(kāi)始的kernel代碼。
       
       
關(guān)于head-xscale.S文件,它定義了xcale處理器的64kcache緩存的實(shí)現代碼和關(guān)閉MMU及緩存的代碼,這些代碼將在鏈接過(guò)程中與head.S的合并。
       
       
關(guān)于misc.c文件,它引入了以下幾個(gè)文件:
                include/linux/kernel.h
                include/asm-arm/arch-pxa/uncompress.h
                include/asm-arm/proc-armv/uncompress.h
                include/asm-arm/uaccess.h
                lib/inflate.c
       
以下分析misc.c文件的decompress_kernel()函數:
        (1)
首先傳入參數:解壓后內核地址,緩存開(kāi)始地址,緩存結束地址,arch id。這些參數通過(guò)寄存器r0(r5),r1,r2,r3(r7)傳入。
        (2)
接著(zhù)執行proc_decomp_setup(),它在include/asm-arm/proc-armv/uncompress.h文件中。主要刷新并起用i cache,鎖住交換緩存,這是一段嵌入的arm匯編代碼。
        (3)
接著(zhù)執行arch_decomp_setup(),它在include/asm-arm/arch-pxa/uncompress.h文件中,是一個(gè)空函數,用于擴展。
        (4)
然后執行makecrc(),它在lib/inflate.c中,主要將產(chǎn)生CRC-32 table,進(jìn)行循環(huán)冗余校驗。
        (5)
調用gunzip()解壓kernel,它也在lib/inflate.c中。
        (6)
返回head.S,解壓后kernel的長(cháng)度傳給r0,解壓后的內核地址預先在r5中定義了。

#3  

3.kernel
進(jìn)入文件分析:
       
隨后系統將調入文件:arch/arm/kernel/head_armv.Sarch/arm/kernel/head_armo.S。對于armkernel而言,有兩套.S文件:_armv.S _armo.S. 選擇_armv.S 還是_armo.S 依賴(lài)于處理器。ARMversion 1, version 2, 都只支持26位的地址空間。version 3開(kāi)始支持32位的地址空間,同時(shí)還向后兼容26位的地址空間。version 4開(kāi)始不再向后兼容26位的地址空間。這里由于Hyper250使用的是version7,故只涉及文件head_armv.S。

       
head_armv.S是內核的入口點(diǎn),在內核被解壓到預定位置后,它將運行。這里簡(jiǎn)要說(shuō)明其主要工作:
        (1)
首先,關(guān)中斷并進(jìn)入保護模式,這里將建立虛擬地址到物理地址的映射。(見(jiàn)第二章內存分析)

        (2)
調用lookup_processor_type,查詢(xún)CUP和其ID是否在.proc.info表中,如果存在,則令r10指向此結構,在CPU的內核入口文件中。如果不是則提示errorp并掛起。關(guān)于r10指向的結構,他所屬的內核入口文件,以Hyper250為例:arch/arm/mm/proc-xcale.S。
       
這里要要注意的是,此處操作的對象是由vmlinux-armv.lds.in鏈接文件定位的段.proc.info中,這個(gè)段定義在proc-xcale.S文件末尾,這里要注意,上面并沒(méi)有使系統進(jìn)入保護模式,所以在這里對.proc.info尋址的時(shí)候,為了得到相對地址,做了一個(gè)相對尋址的變換。這里好象只用了這個(gè)結構的前3位:處理器類(lèi)型值(value),處理器值掩碼(mask),MMU標志值(mmuflags)。這3個(gè)值在分別放在寄存器r5(0x69052100)、r6(0xfffff7f0)、r8(0x00000c0e)中,r5r6只是用于和獲得的處理器的ID相比較,而r8則有兩個(gè)可能的值,分別表示MMU的狀態(tài):如果MMU開(kāi)啟,即CACHE_WRITE_THROUGH,則r8=0x00000c0a,否則r8=0x00000c0e。這里r8的值將會(huì )保持到初始頁(yè)表時(shí)使用。
        r10
此時(shí)指向段.proc.info的開(kāi)始地址。

        (3)
寄存器r1中的系統類(lèi)型值(unique architecture number),這個(gè)系統類(lèi)型值的定義,并且由bootloader傳入。在文件arch/arm/tools/mach-types中:
        machine_is_xxx        CONFIG_xxxx                        MACH_TYPE_xxx                number
        xhyper250R1        ARCH_PXA_XHYPER250R1                PXA_XHYPER250R1                200

        (4)
調用lookup_architecture_type,將以r1的值檢查.arch.info表,這是個(gè)struct machine_desc由文件arch/arm/mach-pxa/xhyper250R1.c中的MACHINE_START()創(chuàng )建。假如沒(méi)有此結構則提示errora并掛起。
       
這里要注意的是,段.arch.info的定位在vmlinux-armv.lds.in文件中緊接.proc.info,這個(gè)段定義在include/asm-arm/mach/arch.h文件中,使用了宏定義MACHINE_START()。文件首先定義了一個(gè)結構體machine_desc,段.arch.info主體部分使用了宏定義MACHINE_START()其中嵌入這個(gè)結構體。
       
通常來(lái)講MACHINE_START()的實(shí)現應該在文件arch/arm/kernel/arch.c中,而這里hyper250的源碼中,MACHINE_START()宏定義在arch/arm/mach-pxa/xhyper250R1.c中完成了定義,下面詳細分析這個(gè)結構:
        (A)MACHINE_START
        MACHINE_START(_type,_name)
這宏開(kāi)始處嵌入一個(gè)靜態(tài)結構machine_desc,并且立即聲明段.arch.info。
        _type
MACH_TYPE(PXA_XHYPER250R1),用以賦值給machine_desc中的nr,這就是系統類(lèi)型值number(200)。
        _name
是描述系統類(lèi)型的字符串,用以賦值給machine_desc中的namechar*。
       
以下幾個(gè)宏定義均在包含在machine_desc的賦值中,也在段.arch.info中。
        (B)MAINTAINER
        MAINTAINER(n)
,這個(gè)n并沒(méi)有賦值給machine_desc結構,n"Hybus Co,. ltd."字符串,公司名字罷了。
        (C)BOOT_MEM
        BOOT_MEM(_pram,_pio,_vio)
,這里面很關(guān)鍵,又3個(gè)變量:
        _pram
,傳值給phys_ram:物理內存的開(kāi)始地址,程序中賦值為:0xa0000000。
        _pio
,傳值給phys_io:物理io的開(kāi)始地址,程序中賦值為:0x40000000。
        _vio
,傳值給io_pg_offstio頁(yè)表的偏移,程序中賦值為:_vio=0xfc000000,不過(guò)要進(jìn)行轉換:((_vio)>>18)&0xfffc=0x3f00
        (D)BOOT_PARAMS
        BOOT_PARAMS(_params)
這個(gè)宏定義了啟動(dòng)參數頁(yè)表的偏移:param_offset,程序中賦值為:0xa0000100。       
        (E)FIXUP(
接下來(lái)三個(gè)宏定義分別是三個(gè)函數指針:這些函數都在machine_desc結構中定義并且在xhyper250R1.c中實(shí)現。)
        FIXUP(fixup_xhyper250R1)
宏指向fixup_xhyper250R1函數,這個(gè)函數有4個(gè)參數:
        fixup_xhyper250R1(struct machine_desc *desc, struct param_struct *params, char **cmdline, struct meminfo *mi)       
        struct machine_desc
:這個(gè)結構體前面已經(jīng)提過(guò)了。
        param_struct
:這個(gè)結構體定義在include/asm/setup.h中,這是一個(gè)向kernel傳遞參數的結構體。
        char **cmdline
:好像用于定義輸出窗口行數。
        struct meminfo
:這個(gè)結構體定義在include/asm/setup.h中,這是一個(gè)對物理內存區間描述的結構體,它將整個(gè)地址空間分為8個(gè)區間,通常一個(gè)區必須是連續的地址并且是同一類(lèi)型的設備,而用于特殊目的的地址將劃分為一個(gè)獨立的區。首先定義nr_banks:塊號,然后是結構體bank[NR_BANKS],NR_BANKS8。結構體bank[NR_BANKS]中有:start、size、node。
       
下面分析這個(gè)函數fixup_xhyper250R1的工作,
       
首先,調用宏SET_BANK并賦值為SET_BANK(0, 0xa0000000, 64*1024*1024),這個(gè)宏定義在arch/arm/mach-pxa/generic.h文件中。SET_BANK主要完成設置結構體meminfobank[_nr]start、sizenode。以上為例,則完成了bank[0]區間中的start=0xa0000000,size=64*1024*1024=64M,node=(__start) - PHYS_OFFSET) >> 27=0
       
接著(zhù),使minr_banks=1,好象設定了這個(gè)結構只有一個(gè)區。要注意的是meminfo將在page_init()中用于初始化頁(yè)面。       
        (F)MAPIO
        MAPIO(xhyper250R1_map_io)
宏指向xhyper250R1_map_io函數,這個(gè)函數沒(méi)有參數,主要用于io地址從虛擬地址到物理地址的映射關(guān)系。
       
這個(gè)函數調用了pxa_map_io()iotable_init(xhyper250R1_io_desc)
        pxa_map_io()
函數定義在arch/arm/mach-pxa/generic.h文件中,實(shí)現在arch/arm/mach-pxa/generic.c中,主要調用了iotable_init()函數來(lái)進(jìn)行io地址的區間映象。iotable_init(struct map_desc *)函數中,參數map_desc結構體定義在文件include/asm-arm/map.h中,主要有:virtual、physical、length和一些標志位:domain、read、write、cache、buffer等。iotable_init()函數在文件arch/arm/mm/mm-armv.c中,循環(huán)調用create_mapping()來(lái)處理map_desc的映射關(guān)系。create_mapping函數主要工作就是將io的虛擬地址到物理地址的映射關(guān)系按照PAGE_SIZE(4K)的頁(yè)來(lái)進(jìn)行映射,同時(shí)還有段的映射關(guān)系。(關(guān)于內存的映射將在第2章中詳細分析)       
        (G)INITIRQ
        INITIRQ(xhyper250R1_init_irq)
指向了xhyper250R1_init_irq函數,這個(gè)函數將主要完成中斷的初始化,這里主要調用了函數 pxa_init_irq(),這個(gè)函數實(shí)現在arch/arm/mach-pxa/irq.c中。接著(zhù)調用了set_GPIO_IRQ_edge()函數,這個(gè)函數也在irq.c中。(關(guān)于中斷的分析將在以后進(jìn)行)

       
我們以上通過(guò)分析宏MACHINE_START而分析了結構體machine_desc的一個(gè)實(shí)例的賦值,我們這里其實(shí)只用這個(gè)結構體很少一部分信息,主要有三個(gè)參數內存物理內存的開(kāi)始地址、物理io的開(kāi)始地址、io頁(yè)表的偏移,分別存于寄存器r5(phys_ram=0xa0000000)、r6(phys_io=0x40000000)、r7(io_pg_offst=0x3f00)中,并返回。

        (5)
初始化頁(yè)表,映射了4MRAM,以使內核運行。
       
這里值得注意的是:r5此時(shí)為物理內存開(kāi)始地址(0xa0000000),程序利用宏定義pgtbl,將r4成為頁(yè)表首地址0xC0004000。然后清空內核目錄swapper_pg_dir開(kāi)始的16K空間。
       
        (6)
設置lr為返回地址__ret,以使下面的程序得以跳轉返回。
        (7)
使pc=[r10+12],也就是跳轉到_xscale_proc_init結構中的b __xscale_setup位置,這個(gè)結構在arch/arm/mm/proc-xcale.S中。我們來(lái)看看這個(gè)結構:
        __pxa250_proc_info:                <--r10
指向這個(gè)地址
                .long   0x69052100
                .long   0xfffff7f0
        #if CACHE_WRITE_THROUGH
                .long   0x00000c0a
        #else
                .long   0x00000c0e        <--
這個(gè)參數傳入了r8
        #endif
                b       __xscale_setup    <--[r10+12]
                .long   cpu_arch_name
                .long   cpu_elf_name
                .long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
                .long   cpu_pxa250_info
                .long   xscale_processor_functions
                .size   __pxa250_proc_info, . - __pxa250_proc_info
       
        __xscale_setup
相關(guān)的程序多是對協(xié)處理器cp15的操作,之中用到了宏F_BIT|I_BIT|SVC_MODE,       
       
相關(guān)的宏定義在文件include/asm-arm/proc-armv/ptrace.h中。
        #define SVC_MODE        0x13
        #define T_BIT           0x20
        #define F_BIT           0x40
        #define I_BIT           0x80
       
        (8)
通過(guò)proc-xcale.S__xscale_setup設置MMU,并通過(guò)__ret返回head_armv.S。
        (9)
__ret返回處設置lr通過(guò)__switch_data返回到__mmap_switched。
        (10)
打開(kāi)MMU,將pipeline清空,以使所有的內存得以正確的訪(fǎng)問(wèn)。并返回到__mmap_switched。
        (11)__mmap_switched
通過(guò)__switch_data獲得數據,并設置了stack pointer。
        (12)
清空BSS,并保存CPU類(lèi)型值(processor ID)以及系統類(lèi)型(machine type)等。
        (13)
跳轉到start_kernel。
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
ARMlinux啟動(dòng)分析
U-Boot啟動(dòng)流程(Linux內核)的分析
《ARM9嵌入式系統設計基礎教程》第12章嵌入式Linux軟件設計
kernel 啟動(dòng)過(guò)程, uimge, zimage,arch/arm/boot/compressed/head.S
Android Factory Reset flow
2.6.18-2內核中對S3C2440的引導啟動(dòng)分析 - Arm s3c2440 - Li...
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久