嵌入式系統更新內核
1. 前言
手里有一塊Friendly ARM的MINI2451的板子,這周試着編譯內核,然后更新一下這個板子的Linux內核,想要更新Linux Kernel 4.1版本,但是種種原因實在是沒有更新成功;於是使用Friendly ARM板子提供的3.6版本的內核,但是他們的內核全都配置好了,你只需要按照常規的方法進行編譯就好了,貌似不能更深入的理解內核, 后來我從kernel.org官網上下載原版內核,然后一點點的把2451這個板子需要文件移植過去,可謂是問題百出啊,也學習到了很多東西。
2. 准備材料
- FriendlyARM 的mini2451板子一塊
- 使用的bootloader是FriendARM提供的閉源Superboot2451.bin
- Linux3.6內核源代碼(在官網下的,純凈的)
- mini2451提供的.config文件
3. 燒寫內核的幾個重點
3.1 拿到全新內核的幾個步驟
我們拿到全新內核的時候,一定要注意幾個步驟,好像並沒有幾個書上由我寫的這么詳細的,基本上都是給一個大體的思路,但是到了真刀真槍上場的時候,真的是問題百出。以下講圍繞這幾個方面進行討論。
a) 修改頂層Makefile
b) Machine ID的處理( 在arch/arm/ 的mach中增加C文件 -> 修改Kconfig -> 修改Makefile文件 )
c) 在arch/arm/tools/mach-types 文件中增加Machine ID
3.1.1 修改頂層的Makefile
Makefile一共要修改2個地方即可:
-
修改arch架構: ARCH ?= arm 注意,arm這幾個后面不要打空格啊,要不然make的時候不識別。
- 修改cross_compile 路徑:CROSS_COMPILE?= /home/user/toolchian/arm-linux-
注意1,CROSS_COMPILE的表述,我這里給的是全路徑,而不是像書籍和網絡博客上給的 arm-linux- ,這里為什么呢?因為你的電腦里面可能裝了不是一個交叉編譯環境的工具鏈,所以這里強烈推薦使用交叉編譯環境的絕對路徑,絕對不會出錯,可以放心大膽的使用。
注意2,arm-linux- 后面不要加空格,否則不會識別的,和ARCH那個選項一樣,都不要有空格。 否則就會拋出:“ make: ** /home/delvis/work/linux-3.6/arch/arm: 是一個目錄。 停止。”的錯誤。
Makefile只需要改這兩個位置就可以了,大可保存。
3.1.2 為了Machine ID准備之修改C文件
路徑就是 -> ./arch/arm/ 里面關於mach-"各種型號",你在教學視頻或者書上經常看見如下的說明:
找一個和你板子型號相近的c文件然后復制一份出來。
我使用的是Linux3.2內核且,我的板子的型號是S3C2451的,所以很理所應當的找到mach-s3c24xx這個文件夾, ! 但是我發現在Linux4.1和Linux2.4版本的內核中沒有mach-s3c24xx這個文件夾,其實沒有什么關系,只要找到和你板子芯片型號相近的就可以的。
我這里是復制FriendlyARM提供的mach-mini2451.c這個文件,在這個文件需要注意幾個地方,我現在還不是很明白這個文件是做什么的,看里面很多初始化的程序包括GPIO、時鍾、定時器、中斷等等,應該是對2451板子進行初始化的。暫時我還不會寫,靠移植吧。
- 文件末尾MACHINE_START( USER_DEFINE_STRING, "USER_DEFINE_STRING" ) { .... } 這個就是MACHINE id 的位置
- 還有其中定義的函數,需要依賴很多頭文件,原生內核里面沒有,缺什么我就從FriendlyARM里面拷貝到相應的目錄。
文件末尾的MACHINE_START傳遞的參數的USER_DEFINE_STRING就是我們一會兒要寫入machine id的宏定義,我這里宏定義的字符串是MACH_MINI2451
3.1.3 修改mach-xxxx中的Kconfig文件
剛才剛剛添加了新的mach-mini2451.c的文件,就要在和這個文件同一個目錄下的Kconfig中加入這個的配置項,我給出我的配置項:
config MACH_MINI2451
bool "MINI2451BYDELVIS"
#select S3C24XX_SMDK
select S3C_DEV_FB
select S3C_DEV_HSMMC
select S3C_DEV_HSMMC1
select S3C_DEV_NAND
select S3C_DEV_USB_HOST
select S3C2416_SETUP_SDHCI
select WIRELESS_EXT
select WEXT_SPY
select WEXT_PRIV
select AVERAGE
help
Say Y here if you are using an FriendlyARM MINI2451
在Kconfig中增加這個字符串,在頂層進行make menuconfig的時候,這個選項就會出來,我們在make menuconfig的時候,最先應該的就是選擇板子的架構
- System Type --> ARM sytem type( Samsung S3C24XX Socs ) --> Samsung S3C24XX SoCs
選擇后返回上一層
2)SASUNG S3C24XX SoCs Support ---> 先選上 SASUNG S3C2416/S3C2450 ---> 下面自動出 MINI2451BYDELVIS 一會兒說這個菜單的顯示邏輯如何的
3)Exit 並且 Save 成為.config
這些菜單的邏輯和歸屬主要是Kconfig決定的,我們的config MACH_MINI2451這個條目要放到正確的位置,不是隨便放一個位置就行,我們的每一個子菜單對於.config來說都是一項配置。
看圖,首先注意兩個畫紅圈的位置,我們講config MACH_MINI2451這一坨放在了 if CPU_S3C2416 ..... endif這個里面,也就是說我們在make menuconfig中選擇了”MINI2451BYDELVIS“這個選項的時候,MACH_MINI2451默認在.config文件CPU為S3C2416,(也可見,我們的mach-mini2451.c文件是復制mach-s3c2416.c文件改裝而來了)
在make menuconfig菜單中,也只有選擇S3C2416這個CPU型號,我們的這個選項才會出現
3.1.3 修改mach-s3c24xx文件下的Makefile文件
我們平白無故的增加了mach-mini2451.c文件,如果進行全局編譯的時候,是不會進行編譯的,因為沒有makefile進行指導編譯,所以我們需要修改這一層的Makefile,當我進行全局編譯的時候,就有規則指導編譯器進行編譯。
# add by Carlos 2017.12.6
obj-$(CONFIG_MACH_MINI2451) += mach-mini2451.o mini2451-lcds.o
在這一層的Makefile文件中隨便找一個位置,然后按照這個格式輸出文件。
3.1.4 增加機器碼
說到機器碼,我真的不得不吐槽一下Friendly ARM,在購買Friendly ARM的時候,購買的宣傳界面,大篇幅的說他們花了重金開發了Superboot2451.bin企業級的bootloader,重點是閉源,bootloader還是不錯的,從SD卡引導,支持串口,驅動支持的挺全的,還有一個他們獨創的可視化界面miniTools的USBMODE一鍵安裝系統,一鍵下載程序。但是好歹閉源的同時,把bootloader的關鍵參數給出啊!!!!我找了他們的Wiki,找了官網,手冊,就是沒有知道Superboot2451.bin的Machine ID,好歹把ID值給出來啊。
恩,后來經過實驗輸出,得到強大的閉源Superboot2451.bin的 機器碼 machine id 是: 0x00000695
好了,吐槽到此為止,我還是建議自己開發uboot,這樣方便。
只有bootloader和kernel中的機器碼一樣,內核才能正常啟動,否則將會拋出:
Error: unrecognized/unsupported machine ID (r1 = 0x33f60264).
我們要么改正uboot中的ID,要么改正kernel中的ID,總之,無論數字是什么,要一樣。
好了,Superboot2451.bin的既然是閉源的就沒辦法進行改正了,那么我們只能改正Kernel中的ID了,那么Kernel中的ID該怎么改正呢?
切換到: arch/arm/tools/文件夾,里面有個mach-types文件,我們在后面追加一個:
mini2451 MACH_MINI2451 MINI2451 0x695
細心的朋友已經發現了,在上面的章節中,零零散散的文件用的也是這些字符,也就是mini2451、MACH_MINI2451、MINI2451這個宏定義都是這個ID值。
到此我們的的內核配置完畢了。
3.2 make menuconfig配置
切換到最后一步,進行make menuconfig進行.config的配置,在韋東山老師的視頻里面,提到這個.config文件來源於三個部分
- 進行make menuconfig配置后的,你需要一條條的進行配置。
- 使用默認配置,在上面修改
- 使用廠家提供的
我這里,使用廠家提供的mini2451_linux_config文件,在上面進行修改,首先就把運行把這個config文件復制過來,並且名字改為.config覆蓋原有的.config文件,然后進行make menucofig,在system type中如同上面講述的選擇正確的板子的型號。如果你沒有選擇,就會出現這樣的異常,在內核編譯到最后的時候,出現編譯kernel出現no machine record defined 錯誤。然后一些鬼一樣的網站給出餿主意,還被大量的博客轉載,簡直就是誤導人,你經過google或者百度,會有一個這樣的解決方案 :
這里給一個!反!面!教!材!:
放狗搜后,按照如下方法可以解決。將arch/arm/kernel/vmlinux.lds的最后兩行(如下),給注釋起來,但都沒說是為了什么
ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support"),
ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined")反面教材來源:uncompressing linux .................................................后沒反應解決辦法 前半部分
簡直是神一樣的操作,出錯了,注釋起來就可以維持了,什么邏輯,簡直是對技術的侮辱!!!我嘗試過了,的確內核編譯通過了,可以把內核傳輸到ARM上面,到Load Kernel的下一步,就拋出了Error: unrecognized/unsupported machine ID (r1 = 0x33f60264). 的異常,顯然是沒有機器碼沒有定義。
注釋這個鬼方法根本就不能用好嗎?誰出的餿主意!!
正確的解法是:
按照我們上面的章節進行配置,順理成章的解決Machine ID的問題: ->
-
Machine ID的處理( 在arch/arm/ 的mach中增加C文件 -> 修改Kconfig -> 修改Makefile文件 )
-
在arch/arm/tools/mach-types 文件中增加Machine ID
-
在make menuconfig的menu中選擇system type,選擇正確的型號,會自動配置到.config
3.3 make
然后開始make就可以了,編譯內核,我一般都喜歡用make -j8 多線程編程,速度快,但是很燒CPU。。。
基本上都是這樣的狀態。。。看溫度。
編譯完成之后,按照Friendly ARM提供的文檔,把zImage文件拷到SD卡正確的路徑,然后從SD卡啟動正常燒寫就好了。
4 總結
看到這樣的輸出的時候,真的很激動,終於內核開始正常解壓了。磨了人好幾天。
第15周主要搞內核的搞完了,最近要忙着復習考試,內核事情可能要稍微緩緩了。以后再慢慢研究。
參考文獻:
[1] 貴氣的博客著.Error: unrecognized/unsupported machine ID (r1 = 0x33f60264)..新浪博客.2011-03-20.
[2]韋東山著.《嵌入式Linux完全開發手冊-應用開發》書籍.
[3]FriendlyARM著.2451開發手冊. 用戶手冊.
版權聲明:
1. 本文為MULTIBEANS團隊研發跟隨文章,未經允許不得轉載。
2· 文中涉及的內容若有侵權行為,請與本人聯系,本人會及時刪除。
3· 尊重成果,本文將用的參考文獻全部給出,向無私的工程師,愛好者致敬。