【原创】linux-2.6.38.7移植到mini2440/micro2440(二)——驱动移植

    本文主要参考了以下连篇博文,并做了一定的扩展与整理,在此向原作者表示感谢。

tslib 1.4 在ARM板Micro2440上移植:http://wenku.baidu.com/view/2dec67d2240c844769eaee8e.html

linux-2.6.38内核移植的经验和疑惑:http://www.arm9home.net/simple/index.php?t11074.html

    这里用到的linux-2.6.38.7相对于linux-2.6.32.2的主要变化有三点,一是ioctl成员变为两个,一是信号量中删除了DECLARE_MUTEX宏定义,最后是删除了S3C2440_GPJ0的定义。

1、ADC驱动(mini2440_adc.c)

DECLARE_MUTEX(ADC_LOCK);

DEFINE_SEMAPHORE(ADC_LOCK);

2、LED驱动(mini2440_leds.c)

    在我的内核中已经使用了LED1和LED2,这里已经修改成了控制剩余的两个LED,否则会导致内核崩溃。修改方法就是删除另两个LED相关的部分,比较简单,这里不再列举。

static int sbc2440_leds_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)

{

    ……

}

改为
static long sbc2440_leds_ioctl(struct file *file, unsigned int cmd, unsigned long arg)

{

    ……

}

 

static struct file_operations dev_fops = {
    .owner = THIS_MODULE,
    .ioctl = sbc2440_leds_ioctl,

   .unlocked_ioctl = sbc2440_leds_ioctl,
};

3、PWM驱动(mini2440_pwm.c)

static int s3c24xx_pwm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
static long s3c24xx_pwm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)

 

.ioctl   =   s3c24xx_pwm_ioctl,
.unlocked_ioctl  =   s3c24xx_pwm_ioctl,

 

init_MUTEX(&lock);
sema_init(&lock, 1);

4、button驱动和backlight驱动

无需做修改

5、CMOS摄像头驱动

    CMOS摄像头涉及5个文件,分别是s3c2440camif.c、s3c2440camif.h、s3c2440_ov9650.c、sccb.c、sccb.h。

sccb.c

static DECLARE_MUTEX(bus_lock);
static DEFINE_SEMAPHORE(bus_lock);

s3c2440_ov9650.c

DECLARE_MUTEX(regs_mutex);
DEFINE_SEMAPHORE(regs_mutex);

s3c2440camif.c

    内核中删除了S3C2440_GPJ0的定义,用S3C2410_GPJ(0),替换后发现也可以用。但是加载该模块后,IIC EEPROM 24C08不能再读取或写入,这里是因为sccb.c中将GPE14和GPE15设为IO方式,而不是IIC方式,在后来也没有改回去。但是在linux-2.6.32中该驱动是可以的,怀疑该问题同内核也有关系,暂时不清楚。这里只是在模块卸载程序的最后添加将GPE14和GPE15改为IIC模式的两条语句,这样修改的结果是,只有在该摄像头模块卸载后才能读写24C08。

s3c2410_gpio_cfgpin(S3C2440_GPJ0, S3C2440_GPJ0_CAMDATA0);
s3c2410_gpio_cfgpin(S3C2410_GPJ(0), S3C2440_GPJ0_CAMDATA0);

static void __exit camif_cleanup(void)

{

    ……

    s3c2410_gpio_cfgpin(S3C2410_GPE(14), S3C2410_GPE14_IICSCL);
    s3c2410_gpio_cfgpin(S3C2410_GPE(15), S3C2410_GPE15_IICSDA);

}

最后再提一点,关于多文件编译成一个模块的Makefile,如下:

ifneq ($(KERNELRELEASE),)
    obj-m := s3c2440camera.o

    s3c2440camera-objs := s3c2440_ov9650.o sccb.o s3c2440camif.o
else

    KDIR  := /home/408/linux-2.6.38.7
    PWD  := `pwd`

all:
 make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-

.PHONY: clean
clean:
    rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.order

endif

6、触摸屏

    触摸屏问题主要是tslib要检测内核input子系统的版本号,详细参考《linux-2.6.38内核移植的经验和疑惑》一文,代码在tslib-1.4/plugins/input-raw.c中,我这里并没有按照该文指出的方法修改,而是直接将比较部分注释掉,编译talib-1.4的方法参考《tslib 1.4 在ARM板Micro2440上移植》,编译完成后只需用编译的input.so(output/lib/ts/input.so)文件替换友善根文件系统中的input.so(/usr/local/lib/ts/input.so)文件即可。

static int check_fd(struct tslib_input *i)
{
    ……

 if (! ((ioctl(ts->fd, EVIOCGVERSION, &version) >= 0) &&
/*  (version == EV_VERSION) && */
    ……
}

 

附注:

1、《linux-2.6.38内核移植的经验和疑惑》部分内容

再补充一个问题:
触摸屏驱动虽然移植成功了可是tslib没有作用,触摸屏还是没有用,
我用ts_test测试终端打印了
tslib: Selected device uses a different version of the event protocol than tslib was compiled for

查看tslib源代码发现打印该信息的语句在tslib的源代码的plugs文件夹中input-raw.c的static int check_fd(struct tslib_input *i)函数中,发现tslib在加载linux触摸屏驱动模块时会检查内核的输入子系统的版本号:
         if (ioctl(ts->fd, EVIOCGVERSION, &version) < 0) {
        fprintf(stderr, "tslib: Selected device is not a Linux input event device/n");
        return -1;
            }
上面程序段将驱动的版本号存放在整型的version中
    if (version != EV_VERSION) {
        fprintf(stderr, "tslib: Selected device uses a different version of the event protocol than tslib was compiled for/n");
        return -1;
    }
该程序将获得的版本号version与本tslib的面向的版本号匹配,若不同则打印:
tslib: Selected device uses a different version of the event protocol than tslib was compiled for
信息

再看arm交叉编译工具中的头文件库中的linux/input.h中的EV_VERSION定义为
    #define EV_VERSION        0x010000
而linux内核include/linux/input.h中的EV_VERSION定义为
    #define EV_VERSION        0x010001
由此可见问题就出现在内核的输入子系统的版本号不匹配的问题

解决办法:
    1.将内核源代码里的include/linux/input.h中的
    #define EV_VERSION        0x010001
    改为:
    #define EV_VERSION        0x010000
    2.将arm交叉编译工具中的头文件库中的
    linux/input.h中的
    #define EV_VERSION        0x010000
    改为
    #define EV_VERSION        0x010001
    再编译tslib库

 2、《tslib 1.4 在ARM板Micro2440上移植》部分内容

    1.首先从网上下载的tslib-1.4.tar.gz
    2.解压 tar xvzf tslib-1.4.tar.gz ; cd tslib
    3.生成configure,这里比一般的开源项目少做一步,要先运行解压目录下的脚本
       ./autogen.sh
    4.用configure 生成Makefile.
       生成脚本:
       ./configure --host=arm-linux --prefix=$PWD/../../output/arm-linux ac_cv_func_malloc_0_nonnull=yes  --enable-inputapi=no
    5.编译安装
       make
       make install-strip #安装strip后的库
       #make install       #安装没有strip库版本.

 

你可能感兴趣的:(c,struct,File,Semaphore,input,linux内核)