#嵌入式Linux最小系統移植# 對uboot移植和裁剪的一點點個人思考和總結
阿新 • • 發佈:2019-01-24
思路:
1.分析啟動流程
2.移植config檔案(smdk440_config)
3.移植包含控制條件編譯巨集的.h檔案(configs/s3c2440.h)
4.移植板級初始化.c檔案(s3c2440.c)
5.移植RAM初始化?DDR?
6.移植NorFlash
7.移植NandFlash
8.uboot應該能啟動了?
//分析啟動流程
1.make xx_config
2.在makefile中有以下依賴關係
%_config:
$(MKCONFIG)
3.在mkconfig中會去解析board.cfg,根據輸入的xx去匹配board.cfg中的TARGET項,提取出ARCH、CPU、SOC、VENDOR等
然後自動生成config.h ,其中config.h中定義了一些關於ARCH、SOC等的巨集,以及包含configs/xx.h標頭檔案來控制uboot中的條件編譯
4. make 生成 uboot.bin
uboot.bin依賴於 OBJ LIB LDS,其中LIB變數為cpu/ drivers/ board/
隨後依次進入各資料夾進行make,生成buitin.o,最後連結成uboot.bin
start.s
...
lowlevel_init.S
...
_main(arm/lib/crt0.S)
board_init_f
board_early_init_f
board_init_r
board_init
start.S 主要完成了:
a.初始化異常向量表
b.設定cpu svc模式,關中斷
c.配置cp15協處理器,設定異常向量入口
d.配置cp15,初始化mmu cache tlb
e.板級初始化,pll memory初始化
一、Uboot從norflash啟動和nandflash啟動的區別
1.norflash啟動
norflash是可以片上執行程式碼(XIP)的,也就是說,將bootloader燒寫到norflash的開始地址後,開發板上電以後,cpu直接從0x00開始執行(也就是在norflash中執行)整個uboot,直到引導核心啟動。
2.nandflash啟動
由於norflash有地址線,因此可以直接執行程式碼,而nandflash只有資料線,因此無法片上執行。開發板上電以後,nandflash控制器會自動把nandflash中的前4 K程式碼拷貝至CPU內部RAM(SRAM-CACHE),
同時把片內SRAM對映到0x00,隨後CPU從0x00開始執行,這個過程程式不需要干涉。但是uboot肯定是大於4K,這樣的話4K以後的程式碼怎麼辦?
所以如果是從nandflash啟動,前4K程式碼首先會設定CPU執行模式,關看門狗,設定時鐘,關中斷,初始化記憶體,初始化nandflash,設定堆疊,然後把整個bootloader搬運到SDRAM中,並跳轉到SDRAM中
執行。
一、總結:
對於Uboot來說,主要有兩大階段,第一階段主要使用匯編語言實現,包括cpu、時鐘、關watchdog、mmu等初始化,並設定堆疊,為C語言呼叫做好準備。
隨後進入board_init_f階段,該階段的主要工作就是初始化Clock、serial和RAM,實現最精簡系統啟動。
最後呼叫board_init_r函式,該階段主要是做了一些mmc、flash、eth等外設的初始化以及環境變數的設定等,最後進入main_loop死迴圈,列印命令列,等待命令輸入和解析。
uboot移植主要涉及幾方面:
1.向board_cfg檔案中新增需要支援的新板,包括SOC、CPU、VENDOR、TARGET等項;
2.向board/資料夾中新增對應的板級函式,如board/samsung/mini2440(mini2440.c Makefile)等;
3.向include/configs資料夾中新增對應的標頭檔案如mini2440.h,這個檔案在mkconfig時會被包含進config.h,用於控制Uboot編譯過程的各條件編譯。
4.修改arch/cpu資料夾下對應的start.S,適配對應的cpu型號(比如主頻、時鐘等)。
5.Uboot可以從norflash、nandflash、RAM啟動,不同的啟動方式在start.S會有不同。
本次Uboot移植主要修改了的資料夾:
u-boot-2012.10\board\samsung\mini2440
u-boot-2012.10\include\configs\mini2440.h
u-boot-2012.10\arch\arm\cpu\u-boot.lds
u-boot-2012.10\arch\arm\cpu\arm920t\start.S
本次uboot移植遇到的坑:
1.一操作全域性變數(賦值等操作)就卡死;一列印(如puts、printf)就卡死,最後發現原因是使用的arm-linux-gcc4.7.3交叉編譯器的原因,換成4.4.3就好了,原因未明。
uboot移植需要知道的點:
1.要完整一個完全新板的uboot移植並沒有想象的那麼簡單:
a.需要對所使用的cpu型號很熟悉(datasheet) ------> 因為要配置時鐘、各暫存器等;
b.需要對某一架構(如arm、ppc)熟悉 ------> 因為在start.S中要配置svc32模式等;
c.需要對某一體系下的彙編指令熟悉(如arm) -----> 因為start.S都是用匯編實現的;
d.需要對外設的硬體特性熟悉 -----> 比如uboot對nandflash的裸讀/寫(還有要熟悉cpu中的nandflash控制器的暫存器讀寫);
2.uboot編譯過程是通過config.h(會包含板級標頭檔案,如mini2440.h)檔案內定義的巨集去控制條件編譯,這是要重點關注的:
a.由於第一點所需要的知識點太過底層,而且一般由晶片廠商實現,如果不想進晶片公司的話,沒有興趣去深入瞭解。因此,關注重點放在了第二點。
在實際的產品開發時,晶片廠商會提供SDK,內含移植好的uboot,但是自研板子的外設不可能和晶片廠商的完全一樣。所以,我們就需要知道如何控制uboot
支援不同的外設。
b.如何知道某個driver是由哪個巨集控制的?-----> 可以去driver/資料夾內找,在Makefile中會通過巨集去控制對應的c檔案是否要包含進去進行編譯。
c.除了支援不同的外設,還需要知道uboot的預設配置在哪改。------> 也是在config.g檔案中的各種巨集定義。
3.uboot的除錯方式:
a.uboot在第一階段沒有初始化串列埠,所以是沒有列印的,這個時候的除錯方式主要是通過點燈來檢視執行狀態。
b.還有可以通過彙編直接操作暫存器來輸出相關資訊。
c.本次除錯還是在確認硬體工作正常的情況下除錯的,因此不會去懷疑硬體問題,只需關注程式碼實現。如果真的是全新的板子,那麼Uboot的除錯難度肯定大幅增加。
UBOOT啟動流程:
時鐘初始化、關看門狗、MMU、TLB初始化 ---> RAM初始化 ---> FLASH_TO_RAM ---> ---> board_init_f --->
串列埠初始化 ---> RAM資訊配置 ---> 程式碼重定位(對RAM空間進行規劃,如堆疊空間等)---> board_init_r --->
NORFLASH初始化 ---> NANDFLASH初始化 ---> ETH乙太網PHY初始化 ---> main_loop ---> 接收命令解析命令