• <code id="zjelh"></code>

          <source id="zjelh"><form id="zjelh"></form></source><acronym id="zjelh"><form id="zjelh"><blockquote id="zjelh"></blockquote></form></acronym>

          1. <acronym id="zjelh"><form id="zjelh"></form></acronym>

            <input id="zjelh"><rt id="zjelh"></rt></input>
            <var id="zjelh"><rt id="zjelh"></rt></var>
            <source id="zjelh"><form id="zjelh"><del id="zjelh"></del></form></source>
            當前位置:首頁 > 嵌入式培訓 > 嵌入式學習 > 講師博文 >
            uboot第一階段詳細分析
            時間:2018-08-16作者:華清遠見

            uboot的第一階段設計的非常巧妙,幾乎都是用匯編語言實現的,下面我們一起來看看它的精妙之處吧!

            首先我們來看一下它的鏈接腳本,通過它我們可以知道它整個程序的各個段是怎么存放的。

            OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
                    OUTPUT_ARCH(arm)
                    ENTRY(_start)
                    SECTIONS
                    {
                            . = 0x00000000;

                    . = ALIGN(4);
                            .text :
                            {
                                    cpu/arm920t/start.o        (.text)
                                    *(.text)//所有的其他程序的代碼段以四字節對齊放在它后面
                            }

                    . = ALIGN(4);
                            .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }//只讀數據段

                    . = ALIGN(4);
                            .data : { *(.data) }//指定讀/寫數據段

                    . = ALIGN(4);
                            .got : { *(.got) }//指定got段,got段式是uboot自定義的一個段,非標準段

                    . = .;
                            __u_boot_cmd_start = .;//把__u_boot_cmd_start賦值為當前位置,即起始位置
                            .u_boot_cmd : { *(.u_boot_cmd) }//指定u_boot_cmd段,uboot把所有的uboot命令放在該段
                            __u_boot_cmd_end = .;//把 __u_boot_cmd_end賦值為當前位置,即結束位置

                    . = ALIGN(4);
                            __bss_start = .;//__bss_start賦值為當前位置,即bss段得開始位置
                            .bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
                            _end = .;//把_end賦值為當前位置,即bss段得結束地址
                    }

            從它我們可以看到,uboot運行的第一個程序是cpu/arm920t/start.S,其他的都有注釋,就不多說了。

            下面我們來看看在fs2410上通過nor flash啟動,u-boot的啟動流程:

            電源一上電之后,pc指針從0x00000000 地址開始執行,也就是說這個時候程序跑在nor flash里面(別忘記,nor flash這個時候接在0x00000000地址,它是可以執行程序的只是速度沒有在ram里面執行快)

            這個時候有人可能會問那s3c2410片內的4kRam映射到哪呢?通過查看芯片手冊這個時候它在0x40000000,如下圖:


            (使用NOR FLASH啟動,設備地址映射圖)

            現在我們知道是那個程序在哪里存儲,從哪個地址運行,下面我們來看看這段程序的匯編代碼:

            在這里我們知道運行的第一條指令是b start_code,呵呵!看到這段代碼的時候許多人都認為_start的值是0x00000000,為什么是這個地址呢? 因為連接腳本上指定了。真的是這樣嗎?我們來看看我們編譯好之后,在u-boot目錄下有個System.map,這里面有各個變量的值,如下圖:

            哈哈,_start的值怎么會是0x33f80000?這是因為在頂層的Makefile里面我們指定了它的連接地址。

            看到那個 -o u-boot了嗎,就是通過它生成ELF格式的u-boot的,里面有個LDFLAGS變量,它是什么呢,我們繼續往下面看:

            (頂層的config.mk里面有這個變量的說明)

            看到了沒有,LDFLAGS里面除了指定鏈接腳本,如果TEXT_BASE不等于空,還加上了-Ttext$(TEXT_BASE),TEXT_BASE的值是多少呢?我們可以在board/samsung/smdk2410/config.mk里面有定義,它的值為0x33f80000。這樣我就可以知道為什么System.map的地址都是0x33f80000。

            好我們來看第一條匯編指令b start_code,從System.map文件我們可以知道,這條指令相當于b 0x33f80050。"0x33f80050"?你是否有疑問,這個時候內存還沒有初始化呢,怎么能跳到內存中去了(sdram的起始地址0x30000000)。呵呵,其實不是這樣的。還記得b指令是相對跳轉指令嗎,它和代碼的位置是無關的,這種精妙的設計才使得后面的指令能繼續的執行。

            下面我們繼續來看它的匯編指令:

            呵呵,這段匯編代碼很好理解,就是設置CPU為 管理模式。

            這段匯編代碼就不分析了,這是跟atmel相關的,我不管它,繼續下面:

            這段匯編代碼也很好理解,就是關掉看門狗,然后關掉所有中斷。

            哦哦,設置時鐘,還記得一上電FCLK是多少嗎,只有12MHZ。

            呵呵!跳轉指令,我們來看看它做了什么,這樣我們先從名字上來猜猜它是什么意思?cpu初始化,初始化什么呢?繼續向下看:

            呵呵,有英文注釋,清cache,關閉MMU。都是用協處理指令實現的,如果看不懂,可以看看協處理器指令。多了解一點就多知道一點,不是嗎?

            從上面可以看到,還有一次跳轉bl lowlevel_init。這里面有干了一些什么呢,我們可以到board/samsung/smdk2410/ lowlevel_init.S去看。呵呵,這里我就不截圖了,其實我們只有知道,它在這里面干了初始化內存操作。

            繼續往下面看:

            呵呵,終于到重點部分了,代碼重定向。下面我們來看看它到底是怎么重定向的:

            Adr r0,_start

            這條匯編指令的意思就是把_start當前代碼存儲的地址賦給r0,假如這段代碼存儲在SDRAM里面,那么r0的值就是0x30000000。現在這段代碼存儲在NOR Flash里面,所以r0的值就是

            0x0000000
                    Ldr r1,_TEXT_BASE

            這條匯編指令的意思是把_TEXT_BASE的值作為地址,把這個地址的內容賦給r1,從下面可以知道:

            _TEXT_BASE里面存儲的內容是TEXT_BASE,也就是0x33f80000,所以r1的值就是0x33f80000

            Cmp r0,r1

            將r0和r1做比較,此時r0 = 0x0000000,r1 = 0x33f80000,顯然不相等,那么執行的就是下面的匯編指令:

            ldr r2, _armboot_start

            由此可以知道r2的值是_start,也就是0x33f80000,也是整個代碼的起始地址。

            Ldr r3, _bss_start

            由u-boot.lds的鏈接腳本可以知道,r3的值是整個代碼得結尾.

            Sub r2,r3,r2

            這條指令的意思是r2 = r3 -r2,即r2 = 代碼結束 - 代碼開始,這樣得到的是r2 = 代碼的大小。

            Add r2,r0,r2

            這條指令的意思是r2 = r0 + r3,即 r2 = 代碼開始 + 代碼大小,這樣得到的是r2 = nor falsh 里面代碼的結尾

            此時我們得到r0 = nor flash 代碼的起始位置,r1 = 0x33f80000(sdram :0x300000000 ~ 0x34000000)

            呵呵,這個時候代碼就被從nor flash里面拷貝到sdram里面了。

            這段代碼的意思是設置一些堆棧

            這段代碼的意思是清bss段,

            呵呵,終于看到pc指針的值被改變了。也就是這個時候,pc指針開始跳到sdram里面執行代碼,這也就到了第二階段(從語言階段),后面的代碼都是用C語言寫得了。先分析到這里,下次我們看第二階段。

            uboot解析:

            U-BOOT 第一階段分析(續)

            Uboot啟動流程分析


            發表評論

            全國咨詢電話:400-611-6270,雙休日及節假日請致電值班手機:15010390966

            在線咨詢: 曹老師QQ(3337544669), 徐老師QQ(1462495461), 劉老師 QQ(3108687497)

            企業培訓洽談專線:010-82600901,院校合作洽談專線:010-82600350,在線咨詢:QQ(248856300)

            Copyright 2004-2018 華清遠見教育集團 版權所有 ,京ICP備16055225號,京公海網安備11010802025203號

            yy4480影院