移植 linux-2.6.22
1 解压
find -name "*defconfig"
修改顶层 Makefile
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-
make s3c2410_defconfig
make menuconfig
make uImage
tftp 下载到sdram 运行,乱码
2 修改代码
MACHINE_START(S3C2440, "SMDK2440")
/* Maintainer: Ben Dooks <ben@fluff.org> */
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.init_irq = s3c24xx_init_irq,
.map_io = smdk2440_map_io,
.init_machine = smdk2440_machine_init,
.timer = &s3c24xx_timer,
MACHINE_END
指针函数 smdk2440_map_io 中设置的晶振频率 和 开发板的不一致,改为12000000
/*修改分区*/
static struct mtd_partition smdk_default_nand_part[] = {
[0] = {
.name = "u-boot",
.offset = 0,
.size = SZ_256K,
},
[1] = {
.name = "params",
.offset = MTDPART_OFS_APPEND,
.size = SZ_128K,
},
[2] = {
.name = "kernel",
.offset = MTDPART_OFS_APPEND,
.size = SZ_2M,
},
[3] = {
.name = "rootfs",
.offset = MTDPART_OFS_APPEND,
.size = MTDPART_SIZ_FULL,
}
};
make uImage
3 把yaffs文件系统加到系统中
cd yaffs2-662466a/
./patch-ker.sh c m linux-tree
把yaffs 源文件 复制到 linux-tree/fs/yaffs 中
make menuconfig
在file system中把yaffs 支持选上
make uImage
一次能过。不用像3.4.2那样,需要修改一些代码
现在生成的uImage内核文件就可以正常启动yaffs2挂载根文件系统了
但是系统在启动时会出现下面的错误
4 修改代码,去掉如下错误,使内核支持USB
usb 1-1: device descriptor read/64, error -62
usb 1-1: new full speed USB device using s3c2410-ohci and address 3
usb 1-1: device descriptor read/64, error -62
usb 1-1: device descriptor read/64, error -62
usb 1-1: new full speed USB device using s3c2410-ohci and address 4
usb 1-1: device not accepting address 4, error -62
usb 1-1: new full speed USB device using s3c2410-ohci and address 5
usb 1-1: device not accepting address 5, error -62
查找错误信息的出现地方:
linux-2.6.22\drivers\usb\core\hub.c下的 hub_port_init 函数中
if (r) {
dev_err(&udev->dev, "device descriptor "
"read/%s, error %d\n",
"64", r);
retval = -EMSGSIZE;
continue;
}
错误码为:-62,那么查找错误码的宏定义出现的地方
发现在include/asm-generic/errno.h中定义了:
#define ETIME 62 /*timer expired*/ timeout 超时了
由于错误出现在 hub_port_init 初始化中的:
r = usb_control_msg(udev, usb_rcvaddr0pipe(),
USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
USB_DT_DEVICE << 8, 0,
buf, GET_DESCRIPTOR_BUFSIZE,
USB_CTRL_GET_TIMEOUT); 的这个函数获取usb设备信息的时候产生了超时
google、baidu 得出的结果是:
确定问题就在ohci-s3c2410.c中的 s3c2410_start_hc
USB的时钟设置不正确或没有设置,导致USB Host的48MHz时钟没有跑起来
关于USB时钟设置可以参考芯片说明书
修改代码:
static void s3c2410_start_hc(struct platform_device *dev, struct usb_hcd *hcd)
{
struct s3c2410_hcd_info *info = dev->dev.platform_data;
/*在网上还找到一种说法*/
unsigned long upllvalue = (0x78<<12) | (0x02<<4) | (0x03);
while(upllvalue!=__raw_readl(S3C2410_UPLLCON) )
{
__raw_writel(upllvalue,S3C2410_UPLLCON);
mdelay(1);
}
dev_dbg(&dev->dev, "s3c2410_start_hc:\n");//这句是原来就有的
/**/
/*modify here*/
/*
unsigned long upllvalue = (0x38<<12)|(0x02<<4)|(0x01);
unsigned long upllvalue1 = (0x38<<12)|(0x02<<4)|(0x02);//
dev_dbg(&dev->dev, "s3c2410_start_hc:\n");//这句是原来就有的
__raw_writel(upllvalue,S3C2410_UPLLCON);
mdelay(20);
__raw_writel(upllvalue1,S3C2410_UPLLCON);
mdelay(20);//
*/
clk_enable(usb_clk);
mdelay(2); /* let the bus clock stabilise */
clk_enable(clk);
if (info != NULL) {
info->hcd = hcd;
info->report_oc = s3c2410_hcd_oc;
if (info->enable_oc != NULL) {
(info->enable_oc)(info, 1);
}
}
}
5 修改配置选项,使内核支持U盘
挂载U盘:mount /dev/uba /mnt
6 修改,使支持网卡
ifconfig eth0 down出现如下错误
ifconfig: SIOCGIFFLAGS: No such device
估计是网卡驱动的事,查看make menuconfig,发现dm9000也配置上了
google baidu搜索下,发现是网卡驱动没有运行。
修改网卡驱动代码:
a 修改linux-2.6.22/arch/arm/plat-s3c24xx/devs.c
加入:
/*加入DM9000网卡支持*/
#include <linux/dm9000.h>
#include <linux/ioport.h>
#define DM9000_BASE 0x20000000 //网卡的基地址,根据板子上DM9000网卡接的位置,我的接到nSGN4上,地址为20000000
static struct resource s3c_dm9000_resource[] ={
[0] = {
.start = DM9000_BASE,
.end = DM9000_BASE +0x03 ,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = DM9000_BASE + 0x4,
.end = DM9000_BASE + 0x4 +0x3 ,
.flags = IORESOURCE_MEM,
},
[2] = {
.start = IRQ_EINT7,//网卡的外部中断接到了CPU的EINT7上
.end = IRQ_EINT7,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,//后面的IORESOURCE_IRQ_HIGHEDGE最好加上,否则会出现还是
} //出现 ifconfig: SIOCGIFFLAGS: No such device
};
static struct dm9000_plat_data s3c_device_dm9000_platdata = {
.flags = DM9000_PLATF_16BITONLY,
};
//平台驱动
struct platform_device s3c_device_dm9000 = {
.name = "dm9000",
.id = -1, //也可以是0,有待考证
.num_resources = ARRAY_SIZE(s3c_dm9000_resource),
.resource = s3c_dm9000_resource,
.dev ={
.platform_data = &s3c_device_dm9000_platdata,
}
};
EXPORT_SYMBOL(s3c_device_dm9000);
/*导出设置*/
b 修改 linux-2.6.22/include/asm-arm/plat-s3c24xx/devs.h 加入:
/*修改加入一行代码*/
extern struct platform_device s3c_device_dm9000;
c 修改 linux-2.6.22/arch/arm/mach-s3c2440/mach-smdk2440.c
static struct map_desc smdk2440_iodesc[] __initdata = { 中加入一个元素
{ /*这里加入DM9000的地址映射*/
.virtual = S3C2410_ADDR(0x02100300),
.pfn = __phys_to_pfn(0x20000300),
.length = SZ_1M,
.type = MT_DEVICE,
}
再修改:
static struct platform_device *smdk2440_devices[] __initdata = { 中加入一个元素
/*修改加入一行代码*/
&s3c_device_dm9000,
d 修改 linux-2.6.22/drivers/net/dm9000.c
加入:
/*加入几个头文件*/
#include <asm-arm/arch/irqs.h>
#include <asm-arm/arch/hardware.h>
#include <asm-arm/arch/regs-gpio.h>
#include <linux/irq.h>
#include <asm/arch-s3c2410/map.h>
#include <asm/arch-s3c2410/regs-mem.h>
#include <asm/arch-s3c2410/irqs.h>
#include <asm/arch-s3c2410/hardware.h>
#include <asm/arch-s3c2410/regs-gpio.h>
修改 static int dm9000_probe(struct platform_device *pdev) 加入:
//******************************tekkaman********************************
unsigned int value;
static int once=0;
if (once) {
return -ENXIO;
}
//tekkaman
value = __raw_readl(S3C2410_BWSCON);
value &= ~(S3C2410_BWSCON_WS4|S3C2410_BWSCON_ST4|S3C2410_BWSCON_DW4_32);
value |= (S3C2410_BWSCON_ST4|S3C2410_BWSCON_DW4_16);
__raw_writel(value, S3C2410_BWSCON);
value=0;
value = (S3C2410_BANKCON_Tacs4|S3C2410_BANKCON_Tcos4|S3C2410_BANKCON_Tacc14|
S3C2410_BANKCON_Tcoh4|S3C2410_BANKCON_Tcah4|S3C2410_BANKCON_Tacp6|
S3C2410_BANKCON_PMCnorm);
__raw_writel(value,S3C2410_BANKCON4);
set_irq_type(IRQ_EINT7,IRQ_TYPE_LEVEL_HIGH );
s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_EINT7);
s3c2410_gpio_pullup(S3C2410_GPF7, 0);
//以上代码完成对网卡所用到的寄存器,中断与中断方式的设置,probe函数在发现网卡时就会自动运行
//******************************tekkaman********************************
可以在 dm9000_init_dm9000() 函数中写死网卡MAC地址的,这里没有写死:
而是使用uboot传入的网卡地址,方法:
unsigned char ne_def_eth_mac_addr[]={0x08,0x08,0x1a,0x2b,0x3c,0x4f};
int i;
for(i=0;i<6;i++)
dev->dev_addr[i] = ne_def_eth_mac_addr[i];
以上这四行代码,在源码中被我注释掉了。
到此,make menuconfig ,加入对DM9000支持,编译,发现能ifconfig eth0 192.168.0.2 up 了
在调试的过程中,遇的问题:
dm9000 Ethernet Driver
dm9000: read wrong id 0x2b2a2928
dm9000: read wrong id 0x2b2a0028
dm9000: wrong id: 0x2b2a0028
dm9000: not found (0).
***********************************************************************************************
*解决方法:.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE 中加入:IORESOURCE_IRQ_HIGHEDGE *
***********************************************************************************************
e 修改挂在NFS
mount -t nfs -o nolock 192.168.0.1:/common/rootfs /mnt 后:
mount: mounting 192.168.0.1:/common/rootfs on /mnt failed: Invalid argument
****************************************************************************
百思不得其解,google baidu了一个下午和晚上:觉得两个方法,比较靠谱:
1 重新配置linux :选上RPC服务,因为所有的NFS服务都需要这个RPC,所以把两个RPC相关的选项选中
2 可能是mount命令不支持nfs操作指令,感觉很靠谱,Invalid argument(无效的参数) 对应-t nfs
解决方法:重新配置busybox,make menuconfig
Linux System Utilities --->
Support mounting NFS file systems on Linux < 2.6.23 选中该选项
make;make install;重新安装到wds_rootfs根文件系统中,重新制作yaffs格式文件系统,烧写到flash 中
重启系统,挂载ok.........
7 制作补丁
diff -urN 原始目录树 修改过的目录树 > xxx.patch
打补丁过程:
cd 原始目录树
patch -p1 ../xxx.patch