Linux-內核-學習筆記(13):移植三星官方內核

Linux-內核-學習筆記(13):移植三星官方內核

一、移植前的準備

當拿到源代碼時,首先要在window下利用SourceInsight創建一個工程,並將uboot源代碼加載到SI中,方便修改和查看函數調用。
項目->新項目->設置項目名、工程路徑->選擇整個uboot文件->添加樹 項目->同步文件(全打鉤)

接着要在linux下創建一份,因爲配置和編譯過程都需要在Linux下進行。將壓縮包通過winshare複製到linux下,並在/root/porting_x210/kernel下解壓開,得到samsung-kernel。
在這裏插入圖片描述

二、移植過程

1、檢查Makefile下的ARCH和CROSS_COMPILE是否正確

問題分析: 對於待移植的內核文件,不一定都是按照你的要求進行配置的,所以在移植前一定要保證符合你的配置,比如架構是否對應你的開發板,交叉編譯工具鏈是否對應你ubuntu下的那個。

解決方法: 打開Makefile文件,修改其中的ARCH和CROSS_COMPILE使他們對應的正確的配置。
在這裏插入圖片描述
修改完成後,需要對內核進行配置和編譯,那麼配置的命令怎麼獲得?
答:我們可以通過ls arch/arm/configs查看能夠配置的開發板,找到一個最適合自己開發版的內容,然後用make xxx的方式編譯它。
在這裏插入圖片描述
最後對內核進行編譯:make -j4。這裏-j4表示用4線程進行編譯。

2、將最初的內核鏡像下載到板卡上

編譯完成後即可得到內核鏡像zImage,我們通過tftp的方式將內核鏡像下載到開發板上:
(1)首先將內核鏡像拷貝到tftp傳輸文件夾下:cp arch/arm/boot/zImage /tftpboot/ -f
(2)在uboot下通過tftp下載:tftp 30008000 zImage
(3)啓動內核:bootm 30008000

問題描述: 啓動內核後可以發現,打印信息停留在Starting kernel ···,這句話是在uboot端打印出來的,說明內核沒有啓動。並且linux內核的自解壓代碼都沒有運行(因爲沒有看到:Uncompressing Linux… done, booting the kernel.)
在這裏插入圖片描述

3、修改自解壓代碼

問題分析: 由於自解壓代碼的信息沒有打印出來,說明zImage根本沒有被解壓成功,內核代碼根本就沒有被運行,當然沒有輸出信息了。所以問題出在解壓相關的部分。通過分析可能的原因是內核配置的解壓後代碼放置的內存地址位置有問題
因爲內核配置的解壓地址應該等於鏈接地址,否則自解壓之後內核無法運行。所以我們要知道內核的鏈接地址等於多少,配置的解壓地址等於多少?由於內核的鏈接地址是一個虛擬地址,而自解壓內核時需要物理地址,所以鏈接地址對應的物理地址應該等於自解壓地址。通過head.S中可以得到,內核的物理地址爲0x30008000,所以自解壓代碼配置的解壓地址爲0x30008000

解決方法: 查看mach-s5pv210下的Makefile.boot文件,發現自解壓地址不對,於是在該文件中添加一個條件編譯選項,使得在定義了CONFIG_MACH_SMDKV210時,能夠對應到正確的自解壓地址。
在這裏插入圖片描述
添加完成後創建cp.sh腳本文件,將對應的文件同步:
在這裏插入圖片描述
結果: 還是沒運行,但是有效果。自解壓代碼解壓打印信息已經出來了。但是內核還沒運行。

4、修改物理地址、檢查機器碼

問題分析: 自解壓代碼信息打印出來,但是內核還沒有啓動,我們需要檢查一下定義的內核啓動地址對不對,會不會是內核找不到到哪裏啓動,還有沒有可能是機器碼不對。

解決方法: 檢查memory.h文件,發現代碼爲在定義了CONFIG_MACH_SMDKV210之後的物理地址爲0x20000000,這顯然不對,我們的物理地址是0x30000000,所以我們需要修改物理地址。
在這裏插入圖片描述
緊接着再去檢查機器碼:我們使用的是SMDKV210開發板的內核,所以對應的開發板信息都在mach-smdkc110.c文件中定義。所有的基本信息通過宏定義爲方式決定,下面用圖分析一下宏定義解析過程:
在這裏插入圖片描述
將相應的位置用宏定義替換,那麼這個結構體爲:

static const struct machine_desc __mach_desc_SMDKV210	\
 __used							\
 __attribute__((__section__(".arch.info.init"))) = {	\
	.nr		= MACH_TYPE_SMDKV210,		\
	.name		= "SMDKV210",
	.phys_io	= S3C_PA_UART & 0xfff00000,
	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
	.boot_params	= S5P_PA_SDRAM + 0x100,
	.init_irq	= s5pv210_init_irq,
	.map_io		= smdkv210_map_io,
	.init_machine	= smdkv210_machine_init,
	.timer		= &s5p_systimer,
};

在這裏插入圖片描述
這個宏用來定義一個包含機器碼的數據結構。這個宏的使用其實是用來定義一個結構體類型爲machine_desc類型的結構體變量名爲__mach_desc_SMDKV210。這個結構體變量會被定義到一個特定段.arch.info.init,因此這個結構體變量將來會被鏈接器鏈接到這個.arch.info.init段中。
總結:這樣的做法就是通過一個mach-xxx.c文件來定義了一個機器碼的開發板的machine_desc結構體變量,這個結構體變量放到.arch.info.init段中後,那麼就表示當前內核可以支持這個機器碼的開發板。從而實現一個機器碼對應一個開發板,那麼我也可以通過include/generated/mach-types.h中用名字查看對應的機器碼。落實到當前開發板和當前內核中來分析,當前我們移植的目標開發板使用S5PV210的CPU,對應三星官方開發板中最適合的是SMDKV210,它的架構信息保存在arch-smdkc110.c文件中,我們通過打開宏CONFIG_MACH_SMDKV210即可實現一系列的創建任務。

在結構體__mach_desc_SMDKV210中有一個元素 .init_machine = smdkc110_machine_init,這個元素定義了一個機器硬件初始化函數,這個函數非常重要,這個函數中綁定了我們這個開發板linux內核啓動過程中會初始化的各種硬件的信息,也是驅動移植重點要看的函數。

結果: 通過修改物理地址和檢查機器碼是否正確,可以發現內核運行了,但是打印出一些錯誤信息。
在這裏插入圖片描述

5、解析內核啓動錯誤

問題分析: 從以上錯誤信息中的PC和LR的值可以看出,程序是執行到dev_driver_string或者max8698_pmic_probe(這兩個是函數或者彙編中的標號)符號部分的時候出錯了。我們就從這兩個符號出發去尋找、思考可能出錯的地方然後試圖去解決。
max8698_pmic_probe看名字是max8698這個電源管理IC的驅動安裝函數部分出錯了,應該是我們的開發板系統中配置了支持這個電源管理IC,於是乎啓動時去加載他的驅動,結果驅動在加載執行的過程中出錯了OOPS了。我們X210開發板上根本就沒有max8698這個電源管理IC,既然硬件都沒有驅動執行了肯定會出錯。

解決方法: 在uboot中是直接改源代碼屏蔽掉那個初始化函數解決的。但是在內核中不能這麼幹,因爲linux kernel是高度模塊化高度可配置的,內核中每一個模塊都是被配置項條件編譯了的,因此要去掉某個模塊的支持,只需要重新配置去掉選項即可,不用改源代碼。所以我們的關鍵就是要找它對應的配置項
通過menuconfig,搜索MAX8698對應的配置項,看看它是否打開了,如果打開則給它關閉:
在這裏插入圖片描述
結果: 通過去掉配置項,max8698報錯內容消失。緊接着出現新的問題,顯示VFS: Cannot open root device “mmcblk0p2” or unknown-block(0,0)。
在這裏插入圖片描述

6、iNand問題解析

問題分析: 得到的內核錯誤信息:Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)。從錯誤信息字面意思來分析,就是內核試圖掛載根文件系統時失敗,失敗的原因是unknown-block(不能識別的塊設備)。
unknown-block(0,0)。在kernel啓動時uboot會傳給內核一個cmdline,其中用root=xx來指定了rootfs在哪個設備上,內核就會到相應的地方去掛載rootfs。譬如我們傳參中:root=/dev/mmcblk0p2,這裏的/dev/mmcblk0p2就是rootfs的設備地址,這個設備文件編號的含義就是mmc設備0的第2個分區(設備0就是在SD0通道上的設備,也就是iNand),這裏的問題就是沒找到mmc設備0的第2分區
爲什麼沒找到mmc設備0的第2分區。一定是因爲kernel啓動過程中加載mmc驅動的時候有問題,驅動沒有發現mmc設備0。問題定位在MMC相關的驅動方面。則需要去移植驅動。

max8698_pmic_probe看名字是max8698這個電源管理IC的驅動安裝函數部分出錯了,應該是我們的開發板系統中配置了支持這個電源管理IC,於是乎啓動時去加載他的驅動,結果驅動在加載執行的過程中出錯了OOPS了。我們X210開發板上根本就沒有max8698這個電源管理IC,既然硬件都沒有驅動執行了肯定會出錯。

解決方法: 該問題涉及到驅動問題,留着放在學習驅動後補充……

7、網卡驅動移植

問題分析: 通過內核打印網卡部分的驅動信息dm9000 dm9000.0: read wrong id 0x2b2a2928,可以得知當前網卡驅動尚未移植。
在這裏插入圖片描述
解決方法: 首先我們要檢查.config中的配置項是否正確,通過menuconfig中查看DM9000確實配置爲了y,那麼這一步完成。
緊接着查看DM9000有關的源代碼部分,mach-smdkc110.c中的smdkc110_machine_init是整個開發板的所有硬件的初始化函數,在這裏加載了的硬件將來啓動時就會被初始化,在這裏沒有的將來啓動時就不管,所以重點對這裏進行修改。
,
在這裏插入圖片描述
然後將修改後的文件同步到ubuntu下:
在這裏插入圖片描述
結果: 啓動內核後發現,網卡驅動成功。
在這裏插入圖片描述

三、總結

內核啓動在head.S中首先進行了三個校驗(CPU id的校驗、機器碼的校驗、tag的校驗),然後創建頁表,然後做了一些不太會出錯的事情,然後b start_kernel。基本上能運行到start_kernel內核移植就不太會出問題了。
(1)如果打印信息僅停留在Starting kernel …,那麼需要檢查解壓代碼之前的那部分。
(2)如果打印信息停留在Uncompressing Linux… done, booting the kernel.,說明解壓過去了,但是內核沒啓動。那麼需要檢查與內核啓動前校驗有關信息,可能某部分校驗沒通過。
(3)如果內核啓動打印了好多信息,但是到最後顯示要重啓,說明內核仍然沒有啓動成功,但是到這步內核基本功能已經啓動,所以關注的重點應該在驅動是否移植好,根文件系統掛載是否成功上。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章