轉自:http://www.aiuxian.com/article/p-2796357.html
電子產品如果沒有了電,就跟廢品沒什么區別,是電賦予了他們生命,然而程序則是他們的靈魂。
小時候一直很好奇,一個個死板的電子產品為什么一上電以后就能夠工作了呢?為什么一個小小芯片就能夠運行我們編寫的程序呢?一個開發板從剛上電到整個操作系統能夠運行起來是怎么辦到的呢?這些東西困擾了好久,參考了好多資料現在才慢慢弄明白其中一些原理。
我們現在接觸的大多數電子產品都是使用數字電路設計出來的,數字電路的精髓就是兩個數字:0和1,這兩個數字千變萬化的組合創造了計算機世界的繽紛多彩,不管是cpu、內存還是其他外設都是通過0和1的變化來進行記錄、交互以及計算。硬件是怎么操作這兩個數字以及這兩個數字是怎么控制硬件工作的,這里不進行討論,那都是一些二極管、三極管、與非門、信號放大取樣編碼等等知識,所以這里將對一個個功能完整的芯片,從上電以后,他們通過電信號完成各種操作的過程進行解析。如果有玩過單片機的同學應該知道,一個cpu加上一個電源,然后外接一個外部晶振就能夠做成一個最小系統了,單片機就能夠在他可憐的64k或者128k內存中運行起來了,這些簡單的控制芯片雖然有它的存在價值,但是它不能滿足日益復雜的計算需求,所以需要更快的運算速度以及更大的運行內存,因此我們會用到更復雜的處理器,比如mips、arm等。下面將使用arm s3c2440 處理器分析上電啟動的過程。
作為一個嵌入式產品,它的多樣性讓它更具有可玩性,以及更容易適應不同的需求,它不像我們的PC啟動方式相對比較單一(ROM啟動),arm啟動方式有從norfalsh啟動、nandflash啟動、SD卡啟動和UBS啟動等,但是他們的啟動原理都是大同小異的。
開始之前,先理清幾個概念:
SDRAM(Synchronous Dynamic Random Access Memory):同步動態隨機存取存儲器,同步是指Memory工作需要步時鍾,內部的命令的發送與數據的傳輸都以它為基准;動態是指存儲陣列需要不斷的刷新來保證數據不丟失;隨機是指數據不是線性依次存儲,而是由指定地址進行數據讀寫,簡單的說,它就是cpu使用的外部內存,即我們常說的內存條。
SRAM是英文Static RAM的縮寫,它是一種具有靜止存取功能的內存,不需要刷新電路即能保存它內部存儲的數據,速度比SDRAM快,一般用作高速緩沖存儲器(Cache)。
norflash:非易失閃存,是一種外部存儲介質,芯片內執行(XIP,eXecute In Place),這樣應用程序可以直接在flash閃存內運行,不必再把代碼讀到系統RAM中,由於它有地址總線,cpu可以直接從norflash中取指,直接從FLASH中運行程序,但是工藝復雜,價格比較貴,容量較小(1~4M),NOR的傳輸效率很高
nandflash:它也是非易失閃存(掉電不丟失)的一種,但是它雖然有數據總線,但是沒有地址總線,所以cpu不能直接從nandflash中取指運行,由於它價格便宜,所以常常用來存儲大量數據,和我們常說的硬盤類似。
下面將解析nandflash啟動和norflash啟動兩種方式(arm s3c2440),其他啟動方式將在uboot代碼部分分析。
一、 Nandflash啟動

首先必須把一個正確的bootload燒寫到nandflash的最低位置,即從0x000開始燒寫。當我們選擇從nandflash啟動開發板的時候,開發板就會啟動連接nandflash的電路結構,當開發板一上電的時候,Nand Flash控制器會自動的把Nand Flash上的前4K數據搬移到CPU的內部RAM中(SRAM-cache),這個內部RAM我們通常稱作stepping stone,同時把這段片內SRAM映射到nGCS0片選的空間(即0x00000000),CPU從內部RAM的0x00000000位置開始啟動(執行),這個過程不需要程序干涉的。
這個過程就是啟動過程的stage1,它將nandflash的前4看內容拷貝到stepping stone中,然后從stepping stone的第一條指令開始執行,這4k內容里面的指令將會完成以下幾個動作:
1.硬件設備初始化
2. 加載U-Boot第二階段代碼到SDRAM空間
3. 設置好棧
4. 跳轉到第二階段stage2代碼入口
從下圖我們可以看到,板子重置以后,內存的映射關系。從圖中可以看到以下幾點:
1.剛開始bank0~bank5是只能映射SROM的,而bank6和bank7才能夠接SDRM,而且每個bank最大接128M的SDRM,所以決定了S3C2440的最大可外接SDRAM是256M;
2.從圖中我們可以看到bank6的起始地址是0x3000_0000, 所以我們在執行stage1的第二個動作(加載U-Boot第二階段代碼到SDRAM空間)時,需要將uboot代碼放到0x3000_000~0x4000_0000區間內(SDRAM內),才能從SDRAM中正常執行stage2;
3.當沒有選擇從nandflash啟動時,Boot internal SRAM(4k)的起始地址是0x4000_0000, 當選擇從nandflash啟動時,Boot internal SRAM(4k)的起始地址是0x00, 因為我們的開發板沒有外接SROM,所以bank1~bank5都是空閑的,而bank0的位置將被Boot internal SRAM(4k)替代,也就是說bank0的前4k就是stepping stone(起步石),板子上電以后,在nandflash的啟動模式下,S3C2440在硬件上會完成下圖中的地址映射,並自動將nandflash中的前4k拷貝到stepping stone中,並從stepping stone的開始地址(0x00)獲取到第一條指令並執行。

經過上面的分析后,我們可以將上面兩圖合並成下圖所示:

前面說了nandflash啟動過程中第一個代碼搬移,下面將解析第二個代碼搬移,這4k代碼首先會設置cpu運行模式,關看門狗,設置時鍾,關中斷,初始化內存,初始化nandflash,設置堆棧,然后將整個bootload搬運到SDRAM中,並跳轉到SDRAM中執行。
基本過程如下圖所示:

關於4k代碼的執行過程將會在后面詳細解釋,而且在新的uboot-2015中,這4k代碼是由uboot_spl.bin完成的,下面將基於uboot-2015.10 列出uboot從上電到啟動內核的整個過程進行概述:

二、norflash啟動
其實理解了nandflash的啟動方式,norflash的啟動也就好理解多了,首先需要知道的是norflash是可以在片上執行代碼(XIP)的,也就是說,我們只需要將bootload燒寫到norflash的開始地址,當開發板上電以后,從內存映射圖可以知道,nor flash會被映射到0x00000000地址(就是nGCS0,這里就不需要片內SRAM來輔助了,所以片內SRAM的起始地址還是0x40000000,不會改變),然后cpu從0x00000000開始執行(也就是在Norfalsh中執行)整個uboot,直到引導內核啟動。
從norflash啟動可以省事多了,不僅如此,我們自己編寫的裸機程序需要調試,一般也是直接燒寫到norflash中進行的,因為只要我們將編譯好的可執行文件放到norflash的開始,開發板上電以后就會從norflash的第一條指令開始取指執行,我們后面寫裸機程序的調試就是用這種方式進行的。
從norflash啟動雖然從開發的角度會很方便(其實也方便不了多少),但是從產品的角度卻增加了它的成本,畢竟norflash還是相對較貴的,我們明明只要一塊nandflash就足夠啟動整個開發板了,就沒必要在產品中添加一塊norflash了,只要代碼改改就能省下不少成本,何樂不為。而且nandflash對產品是必不可少的,因為后面還要存放內核和文件系統,起碼需要幾十兆的空間,用norflash來存儲也不現實。
也許你會想,能不能只用norflash,不用nandflash和SDRAM行不行呢,畢竟norflash即可以存儲,也可以運行程序的啊,從理論來說是可以的,但是了解一下他們的市場價格、運行速度和工作原理,應該就會知道答案了。
總結
這里只例舉了兩種啟動方式,還有其他的啟動方式將在uboot代碼中分析,這篇文章只是一個引子和一個概述,后面將具體分析一個開發板是怎么從一個廢品通上電以后體現了它的價值,請看后面的文章,了解bootload中的前4k代碼到底干了什么!