近来找工作连连碰壁~ 感觉自己的实力还不足,所以打算移植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=)/ 感谢阅读