Linux 3.4.2内核驱动移植笔记

实验平台:Jz2440开发板

一、移植DM9000C网卡驱动

1.移植步骤
1)编译
2) 解决错误
    2.1) 头文件不对:去掉或改名
    2.2) 宏不对:改名使用新宏
    2.3) 有些函数没有了:改名使用新函数

2.移植内核自带的网卡驱动程序
在移植之前,首先我们来看一下mini2440(对应的机器ID为:set machid 7CF)中,是如何支持dm9000网卡的。进入到入口函数,找到结构体:

static struct platform_driver dm9000_driver = {
	.driver	= {
		.name    = "dm9000",
		.owner	 = THIS_MODULE,
		.pm	 = &dm9000_drv_pm_ops,
	},
	.probe   = dm9000_probe,
	.remove  = __devexit_p(dm9000_drv_remove),
};

一般是通过.name这个成员进行匹配的,搜索字符串"dm9000",找到如下结构体(在平台文件中:arch\arm\mach-s3c24xx\mach-mini2440.c):

static struct platform_device mini2440_device_eth = {
	.name		= "dm9000",
	.id		= -1,
	.num_resources	= ARRAY_SIZE(mini2440_dm9k_resource),
	.resource	= mini2440_dm9k_resource,
	.dev		= {
		.platform_data	= &mini2440_dm9k_pdata,
	},
};

然后搜索结构体mini2440_device_eth,找到:

static struct platform_device *mini2440_devices[] __initdata = {
	&s3c_device_ohci,
	&s3c_device_wdt,
	&s3c_device_i2c0,
	&s3c_device_rtc,
	&s3c_device_usbgadget,
	&mini2440_device_eth,  //在这里
	&mini2440_led1,
	&mini2440_led2,
	&mini2440_led3,
	&mini2440_led4,
	&mini2440_button_device,
	&s3c_device_nand,
	&s3c_device_sdi,
	&s3c_device_iis,
	&uda1340_codec,
	&mini2440_audio,
	&samsung_asoc_dma,
};

然后再搜索:mini2440_devices,找到:

platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));

这就是把结构体mini2440_devices添加到内核,里面的关于网卡的结构在里面,最终匹配驱动程序,就可以使用驱动程序了。
(这就是所谓的平台设备平台驱动的东西了,把可变的东西抽象出来放到平台相关的文件中定义,而我们的驱动程序,基本上是不需要改变的,它是稳定的内容,我们移植的时候,只需要把平台层可变的相关结构体加上,需要修改的资源,进行修改就可以了)。
而我们用的是smdk2440(对应的机器ID为:set machid 16a),然后我在mach-smdk2440.c中添加以下函数:

/* 
 * The DM9000 has no eeprom, and it's MAC address is set by
 * the bootloader before starting the kernel.
 */

/* DM9000AEP 10/100 ethernet controller */

#define MACH_SMDK2440_DM9K_BASE (S3C2410_CS4 + 0x300)


static struct resource smdk2440_dm9k_resource[] = {
	[0] = {
		.start = MACH_SMDK2440_DM9K_BASE,
		.end   = MACH_SMDK2440_DM9K_BASE + 3,
		.flags = IORESOURCE_MEM
	},
	[1] = {
		.start = MACH_SMDK2440_DM9K_BASE + 4,
		.end   = MACH_SMDK2440_DM9K_BASE + 7,
		.flags = IORESOURCE_MEM
	},
	[2] = {
		.start = IRQ_EINT7,
		.end   = IRQ_EINT7,
		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
	}
};


static struct dm9000_plat_data smdk2440_dm9k_pdata = {
	.flags		= (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),
};

static struct platform_device smdk2440_device_eth = {
	.name		= "dm9000",
	.id		= -1,
	.num_resources	= ARRAY_SIZE(smdk2440_dm9k_resource),
	.resource	= smdk2440_dm9k_resource,
	.dev		= {
		.platform_data	= &smdk2440_dm9k_pdata,
	},
};

在结构体smdk2440_devices中添加网卡成员:

static struct platform_device *smdk2440_devices[] __initdata = {
	&s3c_device_ohci,
	&s3c_device_lcd,
	&s3c_device_wdt,
	&s3c_device_i2c0,
	&s3c_device_iis,
	&smdk2440_device_eth, /* 添加 */
};

添加头文件:

#include <linux/dm9000.h> 

然后重新编译内核,成功。设置机器id,烧写新内核:

set machid 16a
save
nfs 32000000 192.168.2.122:/home/book/works/first_fs/uImage_new
nand erase.part kernel
nand write 32000000 60000 $filesize

重启开发板,成功启动内核,设置开发IP地址,进行ping测试,成功。
同时使用以下命令挂载网络文件系统,挂载成功。

mount -t nfs -o nolock,vers=2 192.168.2.122:/home/book/works/first_fs /mnt

在这里插入图片描述
成功移植DM9000网卡后,从启动内核打印的信息可以发现之前一直存在的ifconfig: SIOCSIFADDR: No such device也消失了。

二、移植LED、按键驱动

1.移植LED驱动
把之前写好的LED驱动(基于linux2.6内核)拷贝到ubuntu服务器,修改Makefile,把内核路径改为linux3.4.2内核的路径:

KERN_DIR = /home/book/works/linux-3.4.2

然后保存退出,直接make编译,发现如下错误。
在这里插入图片描述
#include <asm/arch/regs-gpio.h>#include <asm/hardware.h>两个头文件去掉,重新make编译,结果如下:
在这里插入图片描述
从编译的结果可以看出,头文件相关的错误已经消失。接下来继续解决class_createclass_device_createclass_device_unregisterclass_destroy等函数的错误。这个我们可以参考一下别的驱动程序时怎么做的。
参考dsp56k.c驱动程序发现缺少了头文件:#include <linux/device.h>,重新编译,结果如下:
在这里插入图片描述
从上图可知剩下的就是class_device_createclass_device_unregister两个函数相关的错误了,继续解决问题。
dsp56k.c驱动程序的入口与出口函数发现,linux3.4.2内核用的是device_createdevice_destroyl两个函数,所以,把

first_class_dev = class_device_create(first_drv_class,NULL,MKDEV(major,0),NULL,"first_dev");
class_device_unregister(first_class_dev);

改为:

first_class_dev = device_create(first_drv_class,NULL,MKDEV(major,0),NULL,"first_dev");
device_destroy(first_drv_class,MKDEV(major,0));

重新编译,结果如下,编译成功。
在这里插入图片描述
重新编译以下测试程序:arm-linux-gcc -o first_drv_test first_drv_test.c
first_drv.kofirst_drv_test拷贝到网络文件系统,测试。
装载驱动程序:insmod first_drv.ko
查看设备:cat cat /proc/deviceslsmod,驱动程序装载成功。
测试:./first_drv_test on./first_drv_test off,开灯、关灯正常。

2. 移植按键驱动
按键驱动的移植与LED驱动移植的步骤相同,移植的过程主要是解决编译出现的错误,添加头文件,修改函数名。

3.移植按键中断驱动程序
驱动程序的移植,主要看编译出现的错误,然后一个个的解决这些错误。
在第三个驱动程序third_drv.c里:
添加的头文件:

#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/device.h>
#include <mach/gpio-nrs.h>
#include <plat/gpio-fns.h>

把下面代码

static struct pin_desc pins_desc[4] ={
	{S3C2410_GPF0,0x01},
	{S3C2410_GPF2,0x02},
	{S3C2410_GPG3,0x03},
	{S3C2410_GPG11,0x04},
};

改为:

static struct pin_desc pins_desc[4] ={
	{S3C2410_GPF(0),0x01},
	{S3C2410_GPF(2),0x02},
	{S3C2410_GPG(3),0x03},
	{S3C2410_GPG(11),0x04},
};

把这个函数

static int third_drv_open (struct inode *inode, struct file *file)
{
    request_irq(IRQ_EINT0,buttons_irq,IRQT_BOTHEDGE,"S2",&pins_desc[0]);
	request_irq(IRQ_EINT2,buttons_irq,IRQT_BOTHEDGE,"S3",&pins_desc[1]);
	request_irq(IRQ_EINT11,buttons_irq,IRQT_BOTHEDGE,"S4",&pins_desc[2]);
	request_irq(IRQ_EINT19,buttons_irq,IRQT_BOTHEDGE,"S5",&pins_desc[3]);
	return 0;
}

改为:

static int third_drv_open (struct inode *inode, struct file *file)
{
    request_irq(IRQ_EINT0,buttons_irq,(IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING	),"S2",&pins_desc[0]);
	request_irq(IRQ_EINT2,buttons_irq,(IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING	),"S3",&pins_desc[1]);
	request_irq(IRQ_EINT11,buttons_irq,(IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING),"S4",&pins_desc[2]);
	request_irq(IRQ_EINT19,buttons_irq,(IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING),"S5",&pins_desc[3]);
	return 0;
}

其他出现的错误解决方法与LED驱动程序移植的方法一样。
注:卸载驱动时出现错误:rmmod: chdir(/lib/modules): No such file or directory
    解决办法:在/lib/目录下创建modules目录:mkdir -p /lib/modules/$(uname -r)

三、LCD驱动移植

1. LCD 驱动移植
同样,在基于linux2.6内核编写的LCD驱动移植到linux3.4.2内核的过程主要是解决编译的错误,解决完错误之后,测试时需要去掉内核自带的LCD驱动程序。
在linux3.4.2内核顶层目录下输入:make menuconfig
依次选择:

Device Drivers  --->
Graphics support  ---> 
<*> Support for frame buffer devices  --->
<*>   S3C2410 LCD framebuffer support 

<*> S3C2410 LCD framebuffer support改为<M> S3C2410 LCD framebuffer support
然后依次:make uImagemake modules
把编译好的uImage改为为uImage_nolcd拷贝到/home/book/works/first_fs/目录,并下载到开发板:

nfs 32000000 192.168.2.122:/home/book/works/first_fs/uImage_nolcd
bootm 32000000
mount -t nfs -o nolock,vers=2 192.168.2.122:/home/book/works/first_fs/ /mnt
cd /mnt
insmod lcd_drv.ko

驱动装载成功后,会弹出:Console: switching to colour frame buffer device 60x34
注:韦东山第二期毕业班视频里make modules,后可以在drivers/video/目录找到这三个文件:cfbcopyarea.kocfbfillrect.kocfbimgblt.ko,但是我make modules后,在drivers/video/目录只找到了s3c2410fb.ko,最后装载LCD驱动程序时并没有弹出缺少这个三个函数:cfb_fillrectcfb_copyareacfb_imageblit
成功启动内核后,输入命令:echo hello > /dev/tty1,会在LCD打印hello 字符串。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

[email protected].

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值