移植2.6.30.4到MINI2440的學習筆記

本文來自:http://blog.chinaunix.net/u1/57901/showart_2019107.html

近來找工作連連碰壁~ 感覺自己的實力還不足,所以打算移植2.6.30.4到MINI2440 上鍛鍊一下自己

這篇學習筆記以失敗爲基礎向前推進~ 重點在於如何發現問題和解決問題的方法,因爲我硬件基礎還不足,所以像DM9000這樣的硬件初始化我會以”暴力”方法來解決~ 哈哈~

下面開始和大家分享我的失敗過程~:

解壓縮內核壓縮文件後進入到目錄中,然後修改Makefile,找到
ARCH ?=
CROSS_COMPILE ?=
這兩項,不修改這兩項的話將會默認使用x86的配置,這裏修改爲
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-
arm-linux- 是交叉編譯器~ 這裏我使用的交叉編譯器爲友善送的arm-linux-gcc-4.3.2.tgz,帶EABI

然後執行make menuconfig,然後進入System Type中看看是否爲ARM體系~
第一行爲ARM system type 說明沒錯~  然後在ARM system type中選擇SamSung “S3C2410...”
隨後在下面出現的S3C2440 Machines中選擇SMDK2440

退出保存~ 執行make zImage
出現ERROR
drivers/video/console/vgacon.c:510:error “PCIMEM_BASE undeclared”
是在vgacon_startup中,vgacon是啥?~ 不認識~ 應該是不必要的東西~ 去掉它~
vim drivers/video/console/Makefile
在裏面看見了這句
obj-$(CONFIG_VGA_CONSOLE) += vgacon.o
然後執行 find ./ -name “Kconfig” | xargs grep “VGA_CONSOLE”
看見config VGA_CONSOLE 在driver/video/console/Kconfig中
也就是說在驅動->視頻->終端中,執行make menuconfig
在Device Drivers->Graphics Support->Console display driver support中發現了VGA text console
去掉它,保存設置後再編譯

編譯完成後將在arch/arm/boot中得到zImage文件

使用SuperVivi的USB加載功能啓動這個內核文件~ 得到下列輸出

zImage magic = 0x016f2818
Setup linux parameters at 0x30000100
linux command line is: "noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0"
MACH_TYPE = 1999
NOW, Booting Linux......
Uncompressing Linux........................................................................................................ done, booting the kernel.

失敗
信息不夠豐富~ 根據kasim大大的指點,在配置中進入Kernel hacking
打開Kernel debugging和Kernel low-level debugging functions 還有 Kernel low-level debugging messages via S3C UART
保存後再編譯

運行 zImage後得下列輸出
zImage magic = 0x016f2818
Setup linux parameters at 0x30000100
linux command line is: "noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0"
MACH_TYPE = 1999
NOW, Booting Linux......
Uncompressing Linux........................................................................................................ done, booting the kernel.

Error: unrecognized/unsupported machine ID (r1 = 0x000007cf).

Available machine support:

ID (hex)        NAME
0000016a        SMDK2440

Please check your kernel config and/or bootloader.

失敗
原來是machine的ID和Supervivi傳遞進來的ID不匹配~
關於machine ID,可以 參考一下這篇文章
<2.6.18-2內核中對S3C2440的引導啓動分析>
雖然版本老了點,但是核心思想還是沒有變

vim arch/arm/mach-s3c2440/mach-smdk2440.c
在最後一段有這句 MACHINE_START(S3C2440 , ”SMDK2440”)
這裏S3C2440就是machine ID的代號~ 呢具體值是多少呢?~
在arch/arm/tools/mach-types中
s3c2440 ARCH_S3C2440 S3C2440 362
原來我們的machine ID是362~
呢bootloader傳遞進來的值是多少呢?~
Error: unrecognized/unsupported machine ID (r1 = 0x000007cf).
注意到沒有?~ 0x7CF轉換成10進制也就是1999
修改mach-types中的對應項
s3c2440 ARCH_S3C2440 S3C2440 1999
雖然這樣就和下面MINI2440 的1999衝突了,但是隻要不加入MINI2440 的配置就沒事

修改後編譯,再執行zImage後得下列輸出

zImage magic = 0x016f2818
Setup linux parameters at 0x30000100
linux command line is: "noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0"
MACH_TYPE = 1999
NOW, Booting Linux......
Uncompressing Linux........................................................................................................ done, booting the kernel.

失敗
咦?~ 啥都沒有?~ 最起碼也應該有個亂碼吧  這時候我的第一反應是會不會沒有 入到start_kernel中
所以馬上編輯init/main.c,在start_kernel的前部加上printk(KERN_INFO “in start_kernel /n”);
但是這個時候內核還沒有初始化,所以printk是沒有作用的~
繼續得到kasim大大的指點,編輯kernel/printk.c中的printk函數
{
    va_list args;
    int r;

#ifdef CONFIG_DEBUG_LL
    extern void printascii(const char *);
    char buff[256];
#endif
    va_start(args, fmt);
    r = vprintk(fmt, args);
#ifdef CONFIG_DEBUG_LL
    vsprintf(buff, fmt, args);
#endif
    va_end(args);

#ifdef CONFIG_DEBUG_LL
    printascii(buff);
#endif
return r;
}

編譯後執行zImage,得下列輸出

zImage magic = 0x016f2818
Setup linux parameters at 0x30000100
linux command line is: "noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0"
MACH_TYPE = 1999
NOW, Booting Linux......
Uncompressing Linux........................................................................................................ done, booting the kernel.
<6>in start_kernel
<6>Initializing cgroup subsys cpuset
<6>Initializing cgroup subsys cpu
<5>Linux version 2.6.30.3 (wolf@ubuntu ) (gcc version 4.3.2 (Sourcery G++ Lite 2008q3-72) ) #4 Wed Aug 5 16:54:49 CST 2009
.........................
.........................

失敗
雖然正常輸出了~ 有進入start_kernel~ 但是爲什麼之前每輸出呢?~ 會不會是沒有找到輸出設備
在輸出中看到這行
<5>Kernel command line: noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0
console=ttySAC0 會不會是沒有ttySAC0這個設備呢~ 在內核中搜索ttySAC 在driver/serial/samsung.c中得到對應項目
這時候我猜想會不會沒有加載samsung.c , 經過一輪Makefile和Kconfig的查詢 , 發現對應選項在Device Drivers->Character devices->Serial drivers中
一看,原來根本就沒有加載Samsung SoC serial support , 選成靜態編譯之後又出現了Support for console on Samsung SoC serial port ,就是它了,選上, 退出的時候順便把Kernel low-level debugging functions給取消了
否則我們設置的printk會自行輸出,就不知道ttySAC有沒有加載成功了

編譯後執行,得下列輸出
zImage magic = 0x016f2818
Setup linux parameters at 0x30000100
linux command line is: "noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0"
MACH_TYPE = 1999
NOW, Booting Linux......
Uncompressing Linux......................................................................................................... done, booting the kernel.
w# €DpñGpGp´ó70ÇC¼ØûÛ»›3ó•ó¸Û0ƒw# €DpñGpGp´ó•tØ›•p¸›7¿³ó•/@û7¼¿[£¼Û3•¼ó;£¸ÀÛ;[7û;D°•€D@GoGpGpíó•t›7•{ð#ßóÄ;›•770ÄÄ3Çß;GoDh}û7wœ´{„[ó7ûÛ›30°ôܸ‡#_sÄ;›•770Øijœ¼DG@ÁôÛ•ûÄ;•sÄ›£Ø›•DŽ³ÃÛ70ÄGpÁ4ßœ»ôGã›30³D˜ßF[s˜£ÀÛû70ÛD8ßÄ4G8ôGv£°ÇÃGpÍ´0ƒ÷# €DpñGš´;óC„[4¸F¸ÄÛtÜàGp}4GGÇ4tD@Ä38ÀGpG߀ôØ Û›Ÿ€ÄÛD/Cûƒ£¸ƒ;7v›Ã30Ü›4Û´£ô¼;C3[;7ù³û770‡¸°[•4tD@Ä38ÀGpG߀´´p‡ƒ•ô¼Û7Ÿ€tÛG»4œØ„Çpíƒw#
.......................................

失敗
但這說明ttySAC加載成功了~  不過爲什麼是亂碼呢?~
這時候就需要對比友善的配置和我們的配置有什麼不同了~
打開友善送的linux-2.6.29,觀察arch/arm/mach-s3c2440/mach-mini2440 .c和我們的2.6.30.4下面的arch/arm/mach-s3c2440/mach-smdk2440.c有什麼不同
由於亂碼主要是時鐘問題,所以我們重點觀察UART的設置和基本設置,其它什麼NAND LCD的就不看先

修改smdk2440_uartcfgs[]
[2] = {
 .ulcon = 0x03,
}

修改s3c24xx_init_clocks(12000000);

然後編譯再運行 ,輸出爲
zImage magic = 0x016f2818
Setup linux parameters at 0x30000100
linux command line is: "noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0"
MACH_TYPE = 1999
NOW, Booting Linux......
Uncompressing Linux......................................................................................................... done, booting the kernel.
[    0.000000] in start_kernel
[    0.000000] Initializing cgroup subsys cpuset
[    0.000000] Initializing cgroup subsys cpu
...........................
最後爲
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)

失敗
終於可以 正常輸出了,但是根文件系統掛載失敗
因爲板子上的根文件系統爲yaffs2 這時候內核還沒有這個文件系統的支持,需要我們加上去
拷貝友善的送的2.6.29下的fs/yaffs2目錄 到我們的fs目錄下
然後修改觀察一下友善的送的2.6.29下的fs/Kconfig 和 fs/Makefile和我們的有什麼不同
在我們的Kconfig中的 source “fs/jffs2/Kconfig” 上面加上 source “fs/yaffs2/Kconfig”
在Makefile中的 obj-$(CONFIG_FAT_FS) += fat/ 上面加上 obj-$(CONFIG_YAFFS_FS) += yaffs2/

然後在配置的 File systems->Miscellaneous filesystems 中選上 “YAFFS2 file system support”  “Autoselect yaffs2 format”  “Cache short names in RAM”

然後編譯運行 ,輸出如下
......................
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)

失敗
還是不行,往上看幾行
VFS: Cannot open root device "mtdblock2" or unknown-block(0,0)
Please append a correct "root=" boot option; here are the available partitions:
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
原來是沒有可用的分區
這個時候就要更正我們的NAND配置了
還是對照友善送的linux-2.6.29,觀察arch/arm/plat-s3c24xx/common-friendly-smdk.c來修改我們的arch/arm/plat-s3c24xx/common-smdk.c

主要修改smdk_default_nand_part[]
{
 [0] = {
  .name = “supervivi”,
  .size = 0x00060000,
  .offset = 0,
},
[1] = {
 .name = “Kernel”,
 .offset = 0x00060000,
 .size = 0x00200000,
},
[2] = {
 .name = “root”,
 .offset = 0x00260000,
 .size = 1024*1024*1024,
},
[3] = {
 .name = “nand”,
 .offset = 0x00000000,
 .size = 1024*1024*1024,
}
};

編譯後運行 ,輸出
VFS: Cannot open root device "mtdblock2" or unknown-block(0,0)
Please append a correct "root=" boot option; here are the available partitions:
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)

失敗
還是不行,連最起碼的分區都沒有看見,會不會是MTD沒有加載呢?~
打開配置進入Device Drivers
Memory Technology Device ......... 前面是個M~ 說明這個模塊是動態加載的,而我們編譯的zImage裏面只有靜態模塊
將MTD選爲靜態加載,然後進入MTD配置中看看還有什麼需要選的
NAND Device Support 這個也是動態,選爲靜態加載
進入NAND Device Support
原來連NAND Flash support for S3C2410/S3C2440 SoC都沒選,馬上選爲靜態加載

保存配置後編譯運行 ,再運行 輸出如下:
NAND device: Manufacturer ID: 0xec, Chip ID: 0xf1 (Samsung NAND 128MiB 3,3V 8-bit)
Scanning device for bad blocks
Creating 4 MTD partitions on "NAND 128MiB 3,3V 8-bit":
0x000000000000-0x000000060000 : "supervivi"
0x000000060000-0x000000260000 : "Kernel"
0x000000260000-0x000040260000 : "root"
mtd: partition "root" extends beyond the end of device "NAND 128MiB 3,3V 8-bit" -- size truncated to 0x7da0000
0x000000000000-0x000040000000 : "nand"
mtd: partition "nand" extends beyond the end of device "NAND 128MiB 3,3V 8-bit" -- size truncated to 0x8000000
...............................
VFS: Cannot open root device "mtdblock2" or unknown-block(0,0)
Please append a correct "root=" boot option; here are the available partitions:
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)

失敗
還是沒有可用分區,雖然成功分辨了分區,但是沒有加載成功,估計還是在MTD的模塊選擇上
這時候需要對照友善的配置,經過對比,發現在友善的配置中靜態編譯了MTD中的下面3個模塊
Direct char device access to MTD devices
Common interface to block layer for MTD ‘translation layers’
Caching block device access to MTD devices
我們也選爲靜態編譯
保存配置後編譯運行 ,輸出如下

List of all partitions:
1f00             384 mtdblock0 (driver?)
1f01            2048 mtdblock1 (driver?)
1f02          128640 mtdblock2 (driver?)
1f03          131072 mtdblock3 (driver?)
No filesystem could mount root, tried:  cramfs
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(31,2)

分區加載成功了,但是文件系統卻不能識別,我們之前不是已經加入了yaffs2麼?~
回到配置中再看,原來是動態編譯,並沒有真正進入到內核之中,選爲靜態編譯~

保存配置後編譯,輸出爲

yaffs: dev is 32505858 name is "mtdblock2"
yaffs: passed flags ""
yaffs: Attempting MTD mount on 31.2, "mtdblock2"
yaffs: auto selecting yaffs2
yaffs_read_super: isCheckpointed 0
VFS: Mounted root (yaffs filesystem) on device 31:2.
Freeing init memory: 128K
Kernel panic - not syncing: Attempted to kill init!

失敗
依然錯誤,這個時候懵了,哪裏錯呢~ 沒辦法,只能對照着友善的配置一個個大模塊對着來改
當改到Kernel Features的時候錯誤消失了,原來需要選上
Use the ARM EABI to compile the kernel
Allow old ABI binaries to run with thie Kernel
爲什麼呢?~ Google了一下,原來友善的根文件系統在編譯的時候也啓用了EABI特性,內核和文件系統需要對上
文件系統用了EABI 內核也要用EABI 內核不用EABI 也只能讀取不用EABI的文件系統
選上這兩項之後再編譯,運行 ,輸出如下
yaffs: dev is 32505858 name is "mtdblock2"
yaffs: passed flags ""
yaffs: Attempting MTD mount on 31.2, "mtdblock2"
yaffs: auto selecting yaffs2
yaffs_read_super: isCheckpointed 0
VFS: Mounted root (yaffs filesystem) on device 31:2.
Freeing init memory: 128K
mount: mounting none on /proc/bus/usb failed: No such file or directory
hwclock: can't open '/dev/misc/rtc': No such file or directory
[01/Jan/1970:00:00:13 +0000] boa: server version Boa/0.94.13
[01/Jan/1970:00:00:13 +0000] boa: server built Mar 26 2009 at 15:28:42.
[01/Jan/1970:00:00:13 +0000] boa: starting server pid=845, port 80

open device leds: No such file or directory
Try to bring eth0 interface up......ifconfig: SIOCGIFFLAGS: No such device
ifconfig: SIOCSIFHWADDR: No such device
ifconfig: SIOCSIFADDR: No such device
route: SIOCADDRT: No such process
Done
ifconfig: SIOCSIFADDR: No such device

Please press Enter to activate this console.
[root@FriendlyARM /]#
成功了,ls後輸出如下
bin         home        lost+found  proc        sys         var
dev         lib         mini2440     root        tmp         www
etc         linuxrc     opt         sbin        usr

不過ifconfig命令沒有成功,繼續來配置網卡
對比友善的mach-mini2440 .c 文件,發現我們的mach-smdk2440.c中的smdk2440_devices[]數組並沒有&s3c_device_dm9k這個結 構,加上,追蹤發現該數據結構在arch/arm/plat-s3c24xx/devs.c中,我們的devs.c中沒有該數據結構的定義,加上
#include <linux/dm9000.h>

static struct resource s3c_dm9k_resource[] = {
 [0] = {
 .start = S3C2410_CS4,
 .end = S3C2410_CS4 + 3,
 .flags = IORESOURCE_MEM,
},
 [1] = {
 .start = S3C2410_CS4 + 4,
 .end = S3C2410_CS4 + 4 + 3,
 .flags = IORESOURCE_MEM,
},
 [2] = {
 .start = IRQ_EINT7,
 .end = IRQ_EINT7,
 .flags = IORESOURCE_IRQ | IRQF_TRIGGER_RISING,
},
};

static struct dm9000_plat_data s3c_dm9k_platdata = {
 .flags = DM9000_PLATF_16BITONLY,
};

struct platform_device s3c_device_dm9k = {
 .name = “dm9000”,
 .id = 0;
 .num_resources = ARRAY_SIZE(s3c_dm9k_resource),
 .resource = s3c_dm9k_resource,
 .dev = {
 .platform_data = &s3c_dm9k_platdata,
}
};
EXPORT_SYMBOL(s3c_device_dm9k);

編譯,出錯,
error : s3c_device_dm9k undeclared here
找不到結構?~ 打開mach-smdk2440.c看看有什麼頭文件
比較顯眼的就是<plat/s3c2410.h><plat/s3c2440.h><plat/devs.h>,我 們剛纔編輯的文件是devs.c呢麼devs.h的可能性較高,通過搜索,這個devs.h在/arch/arm/plat-s3c/include /plat/中,打開,BINGO,裏面都是devs.c的數據定義
加上我們的s3c_device_dm9k
extern struct platform_device s3c_device_dm9k;

再編譯,通過了,不過這個時候先別急,我們只添加了設備,驅動有沒有靜態加載呢?~ 打開配置
Device Drivers->Networks device support->Ethernet(10 or 100Mbit)
DM9000 support沒選上,馬上選爲靜態編譯
保存配置,編譯後運行 ,輸出如下
Try to bring eth0 interface up......
說明DM9000配置成功
使用ping命令進行測試,發現丟包率高達78%
是不是驅動沒設置好呢?~ 比較了一下友善的driver/net/dm9000.c和2.6.30.4的dm9000.c,發現明顯不同
直接 拷貝友善的dm9000.c和dm9000.h過來
編譯後運行 ,順利進入終端,然後運行 PING
丟包改善,基本無丟包

我對這次內核移植的總結是:
一步步來~ 先做好終端輸出 再掛載好根文件系統 最後才考慮其它驅動的配置

到此移植就基本結束了 = 3=)/ 感謝閱讀

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