linux中内核中machine_desc,Linux-内核-学习笔记(13):移植三星官方内核
Linux-內(nèi)核-學(xué)習(xí)筆記(13):移植三星官方內(nèi)核
一、移植前的準(zhǔn)備
當(dāng)拿到源代碼時(shí),首先要在window下利用SourceInsight創(chuàng)建一個(gè)工程,并將uboot源代碼加載到SI中,方便修改和查看函數(shù)調(diào)用。
項(xiàng)目->新項(xiàng)目->設(shè)置項(xiàng)目名、工程路徑->選擇整個(gè)uboot文件->添加樹(shù) 項(xiàng)目->同步文件(全打鉤)
接著要在linux下創(chuàng)建一份,因?yàn)榕渲煤途幾g過(guò)程都需要在Linux下進(jìn)行。將壓縮包通過(guò)winshare復(fù)制到linux下,并在/root/porting_x210/kernel下解壓開(kāi),得到samsung-kernel。
二、移植過(guò)程
1、檢查Makefile下的ARCH和CROSS_COMPILE是否正確
問(wèn)題分析: 對(duì)于待移植的內(nèi)核文件,不一定都是按照你的要求進(jìn)行配置的,所以在移植前一定要保證符合你的配置,比如架構(gòu)是否對(duì)應(yīng)你的開(kāi)發(fā)板,交叉編譯工具鏈?zhǔn)欠駥?duì)應(yīng)你ubuntu下的那個(gè)。
解決方法: 打開(kāi)Makefile文件,修改其中的ARCH和CROSS_COMPILE使他們對(duì)應(yīng)的正確的配置。
修改完成后,需要對(duì)內(nèi)核進(jìn)行配置和編譯,那么配置的命令怎么獲得?
答:我們可以通過(guò)ls arch/arm/configs查看能夠配置的開(kāi)發(fā)板,找到一個(gè)最適合自己開(kāi)發(fā)版的內(nèi)容,然后用make xxx的方式編譯它。
最后對(duì)內(nèi)核進(jìn)行編譯:make -j4。這里-j4表示用4線程進(jìn)行編譯。
2、將最初的內(nèi)核鏡像下載到板卡上
編譯完成后即可得到內(nèi)核鏡像zImage,我們通過(guò)tftp的方式將內(nèi)核鏡像下載到開(kāi)發(fā)板上:
(1)首先將內(nèi)核鏡像拷貝到tftp傳輸文件夾下:cp arch/arm/boot/zImage /tftpboot/ -f
(2)在uboot下通過(guò)tftp下載:tftp 30008000 zImage
(3)啟動(dòng)內(nèi)核:bootm 30008000
問(wèn)題描述: 啟動(dòng)內(nèi)核后可以發(fā)現(xiàn),打印信息停留在Starting kernel ···,這句話是在uboot端打印出來(lái)的,說(shuō)明內(nèi)核沒(méi)有啟動(dòng)。并且linux內(nèi)核的自解壓代碼都沒(méi)有運(yùn)行(因?yàn)闆](méi)有看到:Uncompressing Linux… done, booting the kernel.)
3、修改自解壓代碼
問(wèn)題分析: 由于自解壓代碼的信息沒(méi)有打印出來(lái),說(shuō)明zImage根本沒(méi)有被解壓成功,內(nèi)核代碼根本就沒(méi)有被運(yùn)行,當(dāng)然沒(méi)有輸出信息了。所以問(wèn)題出在解壓相關(guān)的部分。通過(guò)分析可能的原因是內(nèi)核配置的解壓后代碼放置的內(nèi)存地址位置有問(wèn)題。
因?yàn)閮?nèi)核配置的解壓地址應(yīng)該等于鏈接地址,否則自解壓之后內(nèi)核無(wú)法運(yùn)行。所以我們要知道內(nèi)核的鏈接地址等于多少,配置的解壓地址等于多少?由于內(nèi)核的鏈接地址是一個(gè)虛擬地址,而自解壓內(nèi)核時(shí)需要物理地址,所以鏈接地址對(duì)應(yīng)的物理地址應(yīng)該等于自解壓地址。通過(guò)head.S中可以得到,內(nèi)核的物理地址為0x30008000,所以自解壓代碼配置的解壓地址為0x30008000。
解決方法: 查看mach-s5pv210下的Makefile.boot文件,發(fā)現(xiàn)自解壓地址不對(duì),于是在該文件中添加一個(gè)條件編譯選項(xiàng),使得在定義了CONFIG_MACH_SMDKV210時(shí),能夠?qū)?yīng)到正確的自解壓地址。
添加完成后創(chuàng)建cp.sh腳本文件,將對(duì)應(yīng)的文件同步:
結(jié)果: 還是沒(méi)運(yùn)行,但是有效果。自解壓代碼解壓打印信息已經(jīng)出來(lái)了。但是內(nèi)核還沒(méi)運(yùn)行。
4、修改物理地址、檢查機(jī)器碼
問(wèn)題分析: 自解壓代碼信息打印出來(lái),但是內(nèi)核還沒(méi)有啟動(dòng),我們需要檢查一下定義的內(nèi)核啟動(dòng)地址對(duì)不對(duì),會(huì)不會(huì)是內(nèi)核找不到到哪里啟動(dòng),還有沒(méi)有可能是機(jī)器碼不對(duì)。
解決方法: 檢查memory.h文件,發(fā)現(xiàn)代碼為在定義了CONFIG_MACH_SMDKV210之后的物理地址為0x20000000,這顯然不對(duì),我們的物理地址是0x30000000,所以我們需要修改物理地址。
緊接著再去檢查機(jī)器碼:我們使用的是SMDKV210開(kāi)發(fā)板的內(nèi)核,所以對(duì)應(yīng)的開(kāi)發(fā)板信息都在mach-smdkc110.c文件中定義。所有的基本信息通過(guò)宏定義為方式?jīng)Q定,下面用圖分析一下宏定義解析過(guò)程:
將相應(yīng)的位置用宏定義替換,那么這個(gè)結(jié)構(gòu)體為:
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,
};
這個(gè)宏用來(lái)定義一個(gè)包含機(jī)器碼的數(shù)據(jù)結(jié)構(gòu)。這個(gè)宏的使用其實(shí)是用來(lái)定義一個(gè)結(jié)構(gòu)體類(lèi)型為machine_desc類(lèi)型的結(jié)構(gòu)體變量,名為_(kāi)_mach_desc_SMDKV210。這個(gè)結(jié)構(gòu)體變量會(huì)被定義到一個(gè)特定段.arch.info.init,因此這個(gè)結(jié)構(gòu)體變量將來(lái)會(huì)被鏈接器鏈接到這個(gè).arch.info.init段中。
總結(jié):這樣的做法就是通過(guò)一個(gè)mach-xxx.c文件來(lái)定義了一個(gè)機(jī)器碼的開(kāi)發(fā)板的machine_desc結(jié)構(gòu)體變量,這個(gè)結(jié)構(gòu)體變量放到.arch.info.init段中后,那么就表示當(dāng)前內(nèi)核可以支持這個(gè)機(jī)器碼的開(kāi)發(fā)板。從而實(shí)現(xiàn)一個(gè)機(jī)器碼對(duì)應(yīng)一個(gè)開(kāi)發(fā)板,那么我也可以通過(guò)include/generated/mach-types.h中用名字查看對(duì)應(yīng)的機(jī)器碼。落實(shí)到當(dāng)前開(kāi)發(fā)板和當(dāng)前內(nèi)核中來(lái)分析,當(dāng)前我們移植的目標(biāo)開(kāi)發(fā)板使用S5PV210的CPU,對(duì)應(yīng)三星官方開(kāi)發(fā)板中最適合的是SMDKV210,它的架構(gòu)信息保存在arch-smdkc110.c文件中,我們通過(guò)打開(kāi)宏CONFIG_MACH_SMDKV210即可實(shí)現(xiàn)一系列的創(chuàng)建任務(wù)。
在結(jié)構(gòu)體__mach_desc_SMDKV210中有一個(gè)元素 .init_machine = smdkc110_machine_init,這個(gè)元素定義了一個(gè)機(jī)器硬件初始化函數(shù),這個(gè)函數(shù)非常重要,這個(gè)函數(shù)中綁定了我們這個(gè)開(kāi)發(fā)板linux內(nèi)核啟動(dòng)過(guò)程中會(huì)初始化的各種硬件的信息,也是驅(qū)動(dòng)移植重點(diǎn)要看的函數(shù)。
結(jié)果: 通過(guò)修改物理地址和檢查機(jī)器碼是否正確,可以發(fā)現(xiàn)內(nèi)核運(yùn)行了,但是打印出一些錯(cuò)誤信息。
5、解析內(nèi)核啟動(dòng)錯(cuò)誤
問(wèn)題分析: 從以上錯(cuò)誤信息中的PC和LR的值可以看出,程序是執(zhí)行到dev_driver_string或者max8698_pmic_probe(這兩個(gè)是函數(shù)或者匯編中的標(biāo)號(hào))符號(hào)部分的時(shí)候出錯(cuò)了。我們就從這兩個(gè)符號(hào)出發(fā)去尋找、思考可能出錯(cuò)的地方然后試圖去解決。
max8698_pmic_probe看名字是max8698這個(gè)電源管理IC的驅(qū)動(dòng)安裝函數(shù)部分出錯(cuò)了,應(yīng)該是我們的開(kāi)發(fā)板系統(tǒng)中配置了支持這個(gè)電源管理IC,于是乎啟動(dòng)時(shí)去加載他的驅(qū)動(dòng),結(jié)果驅(qū)動(dòng)在加載執(zhí)行的過(guò)程中出錯(cuò)了OOPS了。我們X210開(kāi)發(fā)板上根本就沒(méi)有max8698這個(gè)電源管理IC,既然硬件都沒(méi)有驅(qū)動(dòng)執(zhí)行了肯定會(huì)出錯(cuò)。
解決方法: 在uboot中是直接改源代碼屏蔽掉那個(gè)初始化函數(shù)解決的。但是在內(nèi)核中不能這么干,因?yàn)閘inux kernel是高度模塊化高度可配置的,內(nèi)核中每一個(gè)模塊都是被配置項(xiàng)條件編譯了的,因此要去掉某個(gè)模塊的支持,只需要重新配置去掉選項(xiàng)即可,不用改源代碼。所以我們的關(guān)鍵就是要找它對(duì)應(yīng)的配置項(xiàng)。
通過(guò)menuconfig,搜索MAX8698對(duì)應(yīng)的配置項(xiàng),看看它是否打開(kāi)了,如果打開(kāi)則給它關(guān)閉:
結(jié)果: 通過(guò)去掉配置項(xiàng),max8698報(bào)錯(cuò)內(nèi)容消失。緊接著出現(xiàn)新的問(wèn)題,顯示VFS: Cannot open root device “mmcblk0p2” or unknown-block(0,0)。
6、iNand問(wèn)題解析
問(wèn)題分析: 得到的內(nèi)核錯(cuò)誤信息:Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)。從錯(cuò)誤信息字面意思來(lái)分析,就是內(nèi)核試圖掛載根文件系統(tǒng)時(shí)失敗,失敗的原因是unknown-block(不能識(shí)別的塊設(shè)備)。
unknown-block(0,0)。在kernel啟動(dòng)時(shí)uboot會(huì)傳給內(nèi)核一個(gè)cmdline,其中用root=xx來(lái)指定了rootfs在哪個(gè)設(shè)備上,內(nèi)核就會(huì)到相應(yīng)的地方去掛載rootfs。譬如我們傳參中:root=/dev/mmcblk0p2,這里的/dev/mmcblk0p2就是rootfs的設(shè)備地址,這個(gè)設(shè)備文件編號(hào)的含義就是mmc設(shè)備0的第2個(gè)分區(qū)(設(shè)備0就是在SD0通道上的設(shè)備,也就是iNand),這里的問(wèn)題就是沒(méi)找到mmc設(shè)備0的第2分區(qū)。
為什么沒(méi)找到mmc設(shè)備0的第2分區(qū)。一定是因?yàn)閗ernel啟動(dòng)過(guò)程中加載mmc驅(qū)動(dòng)的時(shí)候有問(wèn)題,驅(qū)動(dòng)沒(méi)有發(fā)現(xiàn)mmc設(shè)備0。問(wèn)題定位在MMC相關(guān)的驅(qū)動(dòng)方面。則需要去移植驅(qū)動(dòng)。
max8698_pmic_probe看名字是max8698這個(gè)電源管理IC的驅(qū)動(dòng)安裝函數(shù)部分出錯(cuò)了,應(yīng)該是我們的開(kāi)發(fā)板系統(tǒng)中配置了支持這個(gè)電源管理IC,于是乎啟動(dòng)時(shí)去加載他的驅(qū)動(dòng),結(jié)果驅(qū)動(dòng)在加載執(zhí)行的過(guò)程中出錯(cuò)了OOPS了。我們X210開(kāi)發(fā)板上根本就沒(méi)有max8698這個(gè)電源管理IC,既然硬件都沒(méi)有驅(qū)動(dòng)執(zhí)行了肯定會(huì)出錯(cuò)。
解決方法: 該問(wèn)題涉及到驅(qū)動(dòng)問(wèn)題,留著放在學(xué)習(xí)驅(qū)動(dòng)后補(bǔ)充……
7、網(wǎng)卡驅(qū)動(dòng)移植
問(wèn)題分析: 通過(guò)內(nèi)核打印網(wǎng)卡部分的驅(qū)動(dòng)信息dm9000 dm9000.0: read wrong id 0x2b2a2928,可以得知當(dāng)前網(wǎng)卡驅(qū)動(dòng)尚未移植。
解決方法: 首先我們要檢查.config中的配置項(xiàng)是否正確,通過(guò)menuconfig中查看DM9000確實(shí)配置為了y,那么這一步完成。
緊接著查看DM9000有關(guān)的源代碼部分,mach-smdkc110.c中的smdkc110_machine_init是整個(gè)開(kāi)發(fā)板的所有硬件的初始化函數(shù),在這里加載了的硬件將來(lái)啟動(dòng)時(shí)就會(huì)被初始化,在這里沒(méi)有的將來(lái)啟動(dòng)時(shí)就不管,所以重點(diǎn)對(duì)這里進(jìn)行修改。
然后將修改后的文件同步到ubuntu下:
結(jié)果: 啟動(dòng)內(nèi)核后發(fā)現(xiàn),網(wǎng)卡驅(qū)動(dòng)成功。
三、總結(jié)
內(nèi)核啟動(dòng)在head.S中首先進(jìn)行了三個(gè)校驗(yàn)(CPU id的校驗(yàn)、機(jī)器碼的校驗(yàn)、tag的校驗(yàn)),然后創(chuàng)建頁(yè)表,然后做了一些不太會(huì)出錯(cuò)的事情,然后b start_kernel?;旧夏苓\(yùn)行到start_kernel內(nèi)核移植就不太會(huì)出問(wèn)題了。
(1)如果打印信息僅停留在Starting kernel …,那么需要檢查解壓代碼之前的那部分。
(2)如果打印信息停留在Uncompressing Linux… done, booting the kernel.,說(shuō)明解壓過(guò)去了,但是內(nèi)核沒(méi)啟動(dòng)。那么需要檢查與內(nèi)核啟動(dòng)前校驗(yàn)有關(guān)信息,可能某部分校驗(yàn)沒(méi)通過(guò)。
(3)如果內(nèi)核啟動(dòng)打印了好多信息,但是到最后顯示要重啟,說(shuō)明內(nèi)核仍然沒(méi)有啟動(dòng)成功,但是到這步內(nèi)核基本功能已經(jīng)啟動(dòng),所以關(guān)注的重點(diǎn)應(yīng)該在驅(qū)動(dòng)是否移植好,根文件系統(tǒng)掛載是否成功上。
與50位技術(shù)專(zhuān)家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的linux中内核中machine_desc,Linux-内核-学习笔记(13):移植三星官方内核的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: linux实验报告用户管理,Linux实
- 下一篇: linux 其他常用命令