【移植驱动到Linux3.4.2内核之二】LCD,触摸屏,按键,USB等驱动程序的移植心得总结

学习交流加

  • 个人qq:
    1126137994
  • 个人微信:
    liu1126137994
  • 学习交流资源分享qq群:
    962535112

文章目录

    • 一移植驱动程序心得体会
    • 二移植LCD驱动程序记录
    • 三移植按键输入子系统驱动程序
    • 四移植触摸屏驱动程序
    • 五移植USB驱动程序

今天移植了按键,LED,LCD,触摸屏等驱动程序,移植驱动程序相对于写驱动程序,就简单得多,前提是得理解驱动程序。
现在来大体总结一下如何移植一个新的驱动程序(不是内核自带的驱动程序)的大体思路以及流程。

一移植驱动程序心得体会

首先呢,我们拿到一个新的驱动程序,直接先拿过来编译(先修改Makefile关于内核的路径),编译后,一般都会报错,因为我们的驱动程序,一般不是针对我们这个内核来写的,报错了不要怕,我们一个一个解决。

错误一般不会太难解决,因为驱动程序关于硬件的操作,都是完全一样的,除非你用的硬件都不一样,那样就得换驱动程序了。一般的错误不会涉及修改硬件的操作,一般都是因为新的内核里面某些函数的名字变了,或者某些函数的定义的形式变了,比如以前是一堆函数在定义,但是有可能在新内核中,这些函数有可能会统一放到一个结构体或者数组中被定义。也有可能这个函数的名字稍微有所变化,也或者是头文件的名字变了,或者缺少了某些头文件。总的来说,大概的错误就是以下几种:

错误:

  1. 解决错误
    1.1 头文件不对:去掉或改名
    1.2 宏不对:改名使用新宏
    1.3 有些函数没有了:改名使用新函数

当我们遇到这样的错误,如果不会解决,就去参考内核中类似的驱动程序,看看别人是怎么实现这些我们错误的功能的,,记住,参考内核源码,是一个非常好的办法,随着经验的提高,这个方法一定要越来越熟悉。然后大概的解决办法,就是上面所说的几种。

之前移植过LED驱动程序,按键等,下面给出一两个移植的过程记录,方便以后查阅复习


二移植LCD驱动程序记录

1.直接编译
首先把我们的LCD的驱动程序以及它的Makefile拿到Linux系统编译,需要将Makefile里依赖的内核目录的路径修改为当前使用的内核路径,然后直接make编译,肯定会报错:
这里写图片描述

2.一个个解决错误
首先解决前面的错误,前三个错误都说,没有相关头文件,那么我们就把这三个头文件注释掉:

//#include <asm/arch/regs-lcd.h>
//#include <asm/arch/regs-gpio.h>
//#include <asm/arch/fb.h>

然后重新编译:
这里写图片描述
这里竟然直接编译通过了,说明新的内核关于LCD的变化不大。

3.测试驱动程序
我们把驱动生成的.ko文件拷贝到网络文件系统,然后还需要重新配置一下内核去掉它本身自带的LCD的支持来验证我们的新编译的驱动是否可以驱动我们的LCD屏。
配置内核:
make menuconfig
依次选择:

 Device Drivers  ---> Graphics support  ---> <*> Support for frame buffer devices  --->   <M>   S3C2410 LCD framebuffer support  //将这一项前面尖括号的*号改成m,这样就去掉了内核自带的LCD驱动

重新编译内核。
编译好内核映像后,还需要make modules,因为我们的LCD驱动程序还依赖于其他三个函数:

static struct fb_ops s3c_lcdfb_ops = {.owner		= THIS_MODULE,.fb_setcolreg	= s3c_lcdfb_setcolreg,.fb_fillrect	= cfb_fillrect,  //下面这三个,这三个函数在三个不同的文件,我们需要把这三个文件编译为.ko文件加载到内核才能.fb_copyarea	= cfb_copyarea,  //使用LCD驱动程序。.fb_imageblit	= cfb_imageblit,
};

然后我把内核映像文件以及生成的三个依赖文件(cfb*ko)拷贝到网络文件系统,烧写内核重启开发板:
设置环境参数:
set bootargs console=ttySAC0,115200 root=/dev/nfs nfsroot=192.168.1.101:/work/nfs_root/fs_mini_mdev_new ip=192.168.1.104:192.168.1.101:192.168.1.1:255.255.255.0::eth0:off

保存环境参数:
save

烧写内核
nfs 30000000 192.168.1.101:/work/nfs_root/uImage_nolcd; bootm 30000000

启动后,先装载cfb*ko文件,然后装载lcd.ko文件,然后用测试程序测试是否可以操作显示屏。一切正常,移植完毕!!!


三移植按键输入子系统驱动程序

1.直接编译
同上lcd驱动的编译先修改Makefile后直接编译:
这里写图片描述

2.改错误
第一个错误:没有某个头文件,那就直接先注释掉。
第二到五的错误:没有定义那个宏,通过搜索内核相关类似驱动程序以及类似函数的用法,得知,应该将下面的结构体:

struct pin_desc pins_desc[4] = {{IRQ_EINT0,  "S2", S3C2410_GPF0,   KEY_L},{IRQ_EINT2,  "S3", S3C2410_GPF2,   KEY_S},{IRQ_EINT11, "S4", S3C2410_GPG3,   KEY_ENTER},{IRQ_EINT19, "S5",  S3C2410_GPG11, KEY_LEFTSHIFT},
};

改为:

struct pin_desc pins_desc[4] = {{IRQ_EINT0,  "S2", S3C2410_GPF(0),   KEY_L},{IRQ_EINT2,  "S3", S3C2410_GPF(2),   KEY_S},{IRQ_EINT11, "S4", S3C2410_GPG(3),   KEY_ENTER},{IRQ_EINT19, "S5",  S3C2410_GPG(11), KEY_LEFTSHIFT},
};

第六个错误:说是下面的IRQT_BOTHEDGE没有定义,可能是新内核的这个标志有所变化(双边沿触发):

		request_irq(pins_desc[i].irq, buttons_irq, IRQT_BOTHEDGE, pins_desc[i].name, &pins_desc[i]);

搜索内核中request_irq函数的相通用法(注意搜索范围可以缩小到/drivers/char目录),最终查到可以用下面的代替:

		request_irq(pins_desc[i].irq, buttons_irq, (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING), pins_desc[i].name, &pins_desc[i]);

先解决这上面的几个错误,重新编译:竟然编译成功了!!!这说明后面没有看的错误,其实是由前面的错误导致的。

3.测试驱动程序
我们把文件系统中/etc/inittab修改为(加一行:tty1::askfirst:-/bin/sh):

::sysinit:/etc/init.d/rcS
console::askfirst:-/bin/sh
tty1::askfirst:-/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r

然后重启系统:
那么开发板显示屏也会出现跟串口显示一样的内容,按下按键,可以直接操作了。按键驱动程序移植成功。


四移植触摸屏驱动程序

1.直接编译:
这里写图片描述

2.改错误
这次我们的错误比较简单,只需要把上面没有的头文件注释掉就行,然后重新编译。

3.tslib测试触摸屏
我们用tslib这个应用程序库来校准测试触摸屏。
首先我们按照下面的步骤编译tslib的库:
编译:
tar xzf tslib-1.4.tar.gz
cd tslib
./autogen.sh

mkdir tmp
echo “ac_cv_func_malloc_0_nonnull=yes” >arm-linux.cache
./configure --host=arm-linux --cache-file=arm-linux.cache --prefix=$(pwd)/tmp
make
make install

安装tslib库:
cd tmp
cp * -rf /work/nfs_root/fs_mini_mdev_new/

然后修改添加好的ts库的文件系统的配置文件:
修改 /etc/ts.conf第1行(去掉#号和第一个空格):

# module_raw input
改为:
module_raw input

然后设置环境变量:
export TSLIB_TSDEVICE=/dev/event1
export TSLIB_CALIBFILE=/etc/pointercal
export TSLIB_CONFFILE=/etc/ts.conf
export TSLIB_PLUGINDIR=/lib/ts
export TSLIB_CONSOLEDEVICE=none
export TSLIB_FBDEVICE=/dev/fb0

校准:
然后输入:
ts_calibrate

然后显示如下:
selected device is not a touchscreen I understand

看来是遇到了错误,去百度搜索关键字,最终得知:

原因非常简单:tslib中的输入系统和内核input系统版本不匹配,当然也有其他原因,不过这是最常见的情况,先分析一下tslib代码,观察这句话在什么情况下被打印就知道了。
将tslib库中c和H文件加入Source Insight,跟踪源码发现,在 input-raw.c文件中有这么一段代码:

static int check_fd(struct tslib_input *i) {struct tsdev *ts = i->module.dev;int version;u_int32_t  bit;u_int64_t  absbit;if (! ((ioctl(ts->fd, EVIOCGVERSION, &version) >= 0) &&(version == EV_VERSION) &&(ioctl(ts->fd, EVIOCGBIT(0, sizeof(bit) * 8), &bit) >= 0) &&(bit & (1 << EV_ABS)) &&(ioctl(ts->fd, EVIOCGBIT(EV_ABS, sizeof(absbit) * 8), &absbit) >= 0) &&(absbit & (1 << ABS_X)) &&(absbit & (1 << ABS_Y)) && (absbit & (1 << ABS_PRESSURE)))) {fprintf(stderr, "selected device is not a touchscreen I understand\n");return -1; }   if (bit & (1 << EV_SYN))i->using_syn = 1;return 0;}

其中关键的是version == EV_VERSION这个判断语句(可以通过注释法测试到底是哪个判断语句导致的打印语句),如果这俩不等,那么就会打印出selected device is not a touchscreen I understand。

tslib中的input版本号是在交叉编译的时候指定的,赋值给version,而EV_VERSION是在内核中定义,笔者做tslib时,用的2.6.39内核,这个EV_VERSION定义在include/linux/input.h中,值是0x010001,而tslib中的version是和交叉编译器相同,查看编译器,在/work/tools/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include/linux/input.h中,值是0x010000,这俩明显不相等,当然不会满足version == EV_VERSION,所以导致错误。

解决办法:
以下提供两种解决方法
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库

我们选用第二种。

然后重新编译tslib库:
make clean
make
make install
然后将库拷贝到网络文件系统。

修改配置文件以及设置环境变量(如上同)
然后校准输入:
ts_calibrate
可以正常校准触摸屏了。
输入:ts_test可以在屏幕上进行画圆。

以上操作,说明触摸屏驱动程序,以及校准程序,都可以正常使用。


五移植USB驱动程序

我们之前写过简单的USB鼠标驱动程序,实现鼠标左键输出字符“l”,右键输出字符“s”,中键输出回车。
跟上面的一样,直接编译USB驱动程序,出现以下错误:
这里写图片描述

去源码中看错误的行出现在:

	usb_buf = usb_buffer_alloc(dev, len, GFP_ATOMIC, &usb_buf_phys);。。。。。。。。。。。。usb_buffer_free(dev, len, usb_buf, usb_buf_phys);

错误说没有定义usb_buffer_alloc和usb_buffer_free,通过查找,找到如下内容:

/* Compatible macros while we switch over */
static inline void *usb_buffer_alloc(struct usb_device *dev, size_t size,gfp_t mem_flags, dma_addr_t *dma)
{return usb_alloc_coherent(dev, size, mem_flags, dma);
}static inline void usb_buffer_free(struct usb_device *dev, size_t size,void *addr, dma_addr_t dma)
{return usb_free_coherent(dev, size, addr, dma);
}

说明,新的内核中,没有直接定义usb_buffer_alloc与usb_buffer_free,而是让他们返回usb_alloc_coherent和usb_free_coherent,所以我们将usb_buffer_alloc与usb_buffer_free分别替换为:usb_alloc_coherent和usb_free_coherent,应该就可以了!!!!

重新编译,成功!!!!
测试步骤较简单,省略!!!

好了经过以上的分析过程,自己对这种非内核自带的驱动程序的移植,有了一定的理解与掌握,相信以后随着经验的丰富,会更加熟练!!!

想一起探讨以及获得各种学习资源加我(有我博客中写的代码的原稿):
qq:1126137994
微信:liu1126137994
可以共同交流关于嵌入式,操作系统,C++语言,C语言,数据结构等技术问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/423265.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

idea 解决jar 的冲突

1.maven 组件会自动去除重复的jar 注意&#xff01;灰色是去重的jar &#xff0c;实体颜色是使用的jar; 2.springboot 关于 Class path contains multiple SLF4J bindings.警告的解决 2.1查询jar的依赖结构: 查询出slf4j-log4j12 查询到然后执行exclude https://blog.csdn.ne…

永远要跟比你更成功的人在一起

永远要跟比你更成功的人在一起 (本文只有在月09日可以学习到。) 在你的朋友圈中&#xff0c;如果你是最成功的那一个&#xff0c;你就不会更成功了。 别怕与大人物打交道。最成功的人都是那些最容易与别人相处打交道的人&#xff0c;当你总是与最顶尖的人在一起时&#xff0c;你…

UML 模型

1.五分钟读懂UML类图 https://blog.csdn.net/soft_zzti/article/details/79811923

【C++深度剖析教程19】前置操作符与后置操作符

今天来学习C中的前置操作符&#xff08;i&#xff09;与后置操作符&#xff08;i&#xff09;。 一回顾 以前在C语言的理论课程中&#xff0c;我们就学过&#xff0c;前置和后置操作符&#xff0c;有一定的区别&#xff1a; 但是我们可以看到下图&#xff0c;发现前置和后…

【C++的深度剖析教程20】类型转换函数上

今天来学习类型转换函数。 一回顾 我们学习C语言的时候&#xff0c;都知道&#xff0c;标准的数据类型之间&#xff0c;是可以做类型的转换的。分为隐式类型转换和强制类型转换。那么强制类型转换呢&#xff0c;比较简单。但是隐式类型转换&#xff0c;却存在诸多问题。下面我…

【C++的深度剖析教程21】类型转换函数下

上一篇文章写了关于普通类型转换为类类型的语法与性质&#xff0c;今天我们来看一下&#xff1a;类类型如何转换为普通类型。 一、类型转换函数&#xff1a; C类中&#xff0c;可以定义类型转换函数&#xff0c;类型转换函数用于将类对象转换为其他类型。 语法规则&#xff…

自定义链表增,删除,链表逆序

工作时间长了&#xff0c;经常用框架&#xff0c;感觉真的成了coding,建议有时间可以刷一下lettcode 时间一长就会忘&#xff0c;写了大半天&#xff0c;记录一下&#xff0c;理解后再写特别简单&#xff0c;链表逆序看了很多博客&#xff0c;写法各式各样&#xff0c;但是感觉…

【C++深度剖析教程22】继承的概念和意义

今天我们来学习C中的继承的概念和意义。 一、类之间的组合关系 问题&#xff1a;类之间是否存在直接的关联关系&#xff1f; 回答&#xff1a;类之间存在组合的关系&#xff0c;整体与部分的关系。 可以看一下生活中的例子&#xff1a; 下面我们以一个简单的程序来看一下…

设计模式笔记(24)---访问者模式(行为型)

Gof定义 表示一个作用于某对象结构中的各元素的操作。它可以在不改变各元素的类的前提下定义作用于这些元素的新的操作。 动机 在软件构建过程中&#xff0c;由于需求的改变&#xff0c;某些类层次结构中常常需要增加新的行为&#xff08;方法&#xff09;&#xff0c;如果直接…

git 提交遇到error:fail to push some refer to 远程地址(url)

最近项目遇到一个问题&#xff0c;就是git 提交老是报错&#xff0c;但是在其他小伙伴&#xff0c;机器上没有事&#xff0c;调试了半天发现是git 提交时 -m ‘信息不能以“#”号开头’ 参考了下面博客&#xff0c;第一种操作方式&#xff1a; https://www.cnblogs.com/zndxal…

前端学习(95):ps基本操作与图片格式

jpg 色彩比较丰富 gif 动图 png 半透明 psd原始图片

【C++深度剖析教程23】继承中的访问级别

本C课程学习记录&#xff0c;完全来源于狄泰软件学院的相关课程&#xff0c;想一起学习的加我q1126137994或者q群199546072 给你推荐更多相关课程。 今天学习C中继承的访问级别。首先我们思考一个问题&#xff0c;子类是否可以直接访问父类的私有成员&#xff1f;&#xff1f…

【Makefile由浅入深完全学习记录1】认识make和makefile

学习交流加 个人qq&#xff1a; 1126137994个人微信&#xff1a; liu1126137994学习交流资源分享qq群&#xff1a; 962535112 今天开始学习项目又多了一项&#xff1a;Makefile由浅入深完全学习。之前做嵌入式Linux时&#xff0c;就一直在用make&#xff0c;但是对Makefile的理…

前端学习(96):切图流程

按下屏幕的prtscr 找到打开所在的文件 矩形框选中---ctrlc ---controlN------保存-----ctrlv 保存为jpg文件

【C++深度剖析教程24】C++中不同的继承方式

过完年了&#xff0c;今天开始写博客记录学习的过程。继续C的学习&#xff0c;今天我们来看C中不同的继承方式。 一、初探继承的方式 从上图看&#xff0c;是否可以将继承中的public换成protected或者private。如果可以&#xff0c;它们与public继承的区别是什么&#xff1f; …

前端学习(97):psd切图流程

编辑----首选项---增效工具----启用生成器 文件---生成----图像资源 选择图层修改命名为png&#xff0c;则再默认路径下生成。 默认为半透明

【C++深度剖析教程25】继承中的构造与析构

今天来学习C中继承的构造与析构&#xff0c;有兴趣一起学习的加qq&#xff1a;1126137994 1、问题 如何初始化父类成员&#xff1f;父类构造函数与子类构造函数有什么关系&#xff1f; 子类对象是如何构造的&#xff1f; 子类中可以定义构造函数子类构造函数必须对继承而来…

springboot创建子模块时遇到子模块覆盖父模块问题解决

1.最近更新git dev 开发分支需要添加一个子模块&#xff0c;创建过程中遇到 创建springboot 模块时&#xff0c;子模块覆盖了父模块&#xff0c;搞了半天&#xff0c;最后查询到解决办法如下&#xff1a; 1 多模块项目创建 因为本系列的下一篇是《Spring Boot集成Dubbo》&…

【C++深度剖析教程27】多态的概念与意义

今天来学习一个新的概念&#xff0c;多态&#xff01;&#xff01;&#xff01;多态在C编程中具有重要的地位与意义&#xff0c;是面向对象的一个重要思想&#xff01; 加qq1126137994一起学习更多技术~ 1、问题引入 父类与子类之间具有赋值兼容性; *子类对象可以当做父类对…

java编程思想学习(3):Java中的private、protected、public和default的区别

&#xff08;1&#xff09;对于public修饰符&#xff0c;它具有最大的访问权限&#xff0c;可以访问任何一个在CLASSPATH下的类、接口、异常等。它往往用于对外的情况&#xff0c;也就是对象或类对外的一种接口的形式。 &#xff08;2&#xff09;对于protected修饰符&#xf…