700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 嵌入式Linux系统之I.MX6触摸屏驱动程序TSC.C的分析 移植与校准

嵌入式Linux系统之I.MX6触摸屏驱动程序TSC.C的分析 移植与校准

时间:2024-01-18 01:37:44

相关推荐

嵌入式Linux系统之I.MX6触摸屏驱动程序TSC.C的分析 移植与校准

学习交流加

个人qq:

1126137994个人微信:

liu1126137994学习交流资源分享qq群:

962535112

今天来记录一下I.MX6开发板移植触摸屏驱动程序的过程分析。在移植驱动程序之前,为了学习,先去分析一下触摸屏驱动程序的框架。加qq1126137994 一起学习更多技术。

文章目录

1、tsc.c触摸屏驱动程序的分析2、tsc.c触摸屏驱动程序的移植3、触摸屏的校准

1、tsc.c触摸屏驱动程序的分析

I.MX6的触摸屏驱动程序的文件名为:TSC.C。

在tsc.c文件中初始化tsc_init函数注册tsc_driver结构体,当tsc_driver结构体成员驱动name与平台设备层中name匹配相同时调用tsc_probe初始化函数,该函数是tsc设备驱动函数的入口。imx6的具体tsc设备驱动的实现的主要工作在tsc_probe里完成。

下面是分析tsc_probe函数的调用关系(并非程序源码,只是列举出关键的函数调用):

tsc_probeinput_dev = input_allocate_device();//(向input核心层申请)分配一个input_dev结构体。INIT_DELAYED_WORK;//初始化工作队列,把tsc工作任务注册到工作队列中,为下面执行队列的任务作好准备。tsc_work;//通过input_report_abs函数向上层上报触摸屏屏的X、Y坐标和压力值,执行tsc_calculate_pressure函数进行压力校准,init_platform_hw;//?input_set_abs_params;//通过input_dev结构体设置按键和绝对位置事件以及事件下需要处理的ABS_X、ABS_Y、ABS_PRESSURE的具体事件内容request_irq(ts->irq, tsc_irq, 0,client->dev.driver->name, ts);//为tsc中断引脚申请一个中断处理函数,schedule_delayed_work;//中断的上半部分tsc_work; //中断的下半部分,tsc_read_values;//读取xy坐标 以及获取压力值tc->y = tsc_xfer(tsc, READ_Y);tc->x = tsc_xfer(tsc, READ_X);tsc_xfer(tsc, PWRDOWN);//另一次循环测量rt = tsc_calculate_pressure // 计算压力 input_report_abs(input, ABS_X, tc.x);input_report_abs(input, ABS_Y, tc.y);input_report_abs(input, ABS_PRESSURE, rt);//上报获取到的值tsc_xfer;data = i2c_smbus_read_word_data; //检测IIC总线的读写操作val = swab16(data) >> 4; //去掉低4位无效数据(#defineMAX_12BIT 由定义知最大为12bit,所以需要去掉低4位)return val;//tsc_xfer返回一个val值,就是xy坐标的值input_register_device; //像input核心层注册input_dev结构体arch\mips\boot\Elf2ecoff.c中有如下定义#define swab16(x) \(( \(((x) & 0x00ffU) << 8) | \(((x) & 0xff00U) >> 8) )) //将x的值的高8位和低8位互换

当按下触摸板后产生中断,中断里面调用延时函数进入底半部程序。在调度函数里面,先读取坐标,计算压力,然后根据压力大小上报坐标。若触摸板一直按下,那么就重新调用,并通过压力值来看触摸板是否释放。

2、tsc.c触摸屏驱动程序的移植

触摸屏驱动程序的核心部分分析完了,下面就开始移植触摸屏驱动程序,其实,内核自带的驱动程序移植起来非常简单,在理解驱动程序的前提下,在平台设备文件中添加一些私有数据信息,以及配置中断引脚等即可。

IMX6的板级初始化函数:Board-mx6q_sabresd.c

由与tsc与imx6之间的通信是通过IIC总线进行的,因此在imx6的平台设备层(platform_device)的mx6_sabresd_board_init函数里就需要配置与tsc有关的IIC总线。由于是TSC所挂的IIC总线是第二根,在平台初始化函数里将会调用i2c_register_board_info函数注册mxc_i2c2_board_info结构体数组。

向mxc_i2c2_board_info结构体数组里添加如下成员:

{I2C_BOARD_INFO("tsc",0x48),.platform_data = (void *)& tsc_data_lyy,.irq = gpio_io_irq(SABRESD_TS_INT),}

其中由于TSC的A0、A1两个引脚下拉,通过I2C_BOARD_INFO函数注册的从机设备地址是0x48;通过gpio_to_irq函数获取TSC中断号,之后会传给平台驱动层,当申请中断会用到;

再构建tsc_data_lyy结构体,并添加4个成员:init_platform_hw函数、get_pendown_state函数、irq_pin中断引脚的选择、触摸屏驱动相关参数。

/* * 注意:一下添加的函数,位置没有固定要求,但是为了整齐统一,还是把它放到与其它设备定义的相通的位置,方便以后查看*/#ifdef CONFIG_TOUCHSCREEN_TSC#include <linux/i2c/tsc.h>(在头文件里也添加一下)static int tsc_hw_init(void){int err;err = gpio_request(SABRESD_TS_INT,"tsc irq");if(err<0){pr_err("tsc irq gpio request err\n");return err;}err = gpio_direction_input(SABRESD_TS_INT);if(err<0){pr_err("tsc irq gpio init input err %d\n",err);gpio_free(SABRESD_TS_INT);return err;}printk("tsc irq gpio init success!\n");return 0;}static void tsc_hw_remove(void){gpio_free(SABRESD_TS_INT);}static int tsc_get_pendown_state(void){int state;state = gpio_get_value(SABRESD_TS_INT);//printk("tsc get state = %x\n",state);return (state == 0)? 1:0;}static struct tsc_platform_data tsc_data_lyy= {.model = ,.x_plate_ohms =180,.init_platform_hw = tsc_hw_init,.exit_platform_hw = tsc_hw_remove,.get_pendown_state = tsc_get_pendown_state,};#endif

更改中断引脚号:

将宏SABRESD_TS_INT改为:(之前是3,26)#define SABRESD_TS_INTIMX_GPIO_NR(6, 7) //lyy (申请中断引脚)

注:在Linux启动的时候会将信息进行收集,i2c适配器会扫描已经静态注册的i2c_board_info,通过调用i2c_register_board_info函数将包含所有I2C设备的i2c_board_info信息的i2c_devinfo变量加入到__i2c_board_list链表中,并调用i2c_new_device为其实例化一个i2c_client。在驱动加载的时候遇到同名的i2c_board_info就会将i2c_client和driver绑定,并且执行driver的probe函数。这种方式一般放在平台的代码中。

i2c_register_board_info(2, mxc_i2c2_board_info,ARRAY_SIZE(mxc_i2c2_board_info));

注释:

上面的工作,基本完成了驱动程序的移植,但是后来经过测试,发现显示有错误:

Failed to register i2c client tsc at 0x48 (-16)

Can’t create device at 0x48

一开始以为是i2c总线没有识别到,但是经过调试,发现是中断引脚的复用了。

1、首先确定中断的引脚,查看原理图知使用的是:MX6Q_PAD_NANDF_CLE__GPIO_6_7,在mach-mx6\Board-mx6q_sabresd.h 中加入定义:MX6Q_PAD_NANDF_CLE__GPIO_6_7,当然如果有其它设备用了这个引脚,要将其注销2、在板极文件board-mx6q_sabresd.c中注册和申请I2C驱动首先申请中断的信号,并注释掉原来关于GPIO_6_7的引脚(不然无法识别tsc设备)添加头文件:#define SABRESD_TS_INTIMX_GPIO_NR(6, 7) //lyy注释掉之前的://#define SABRESD_CAP_TCH_INT1IMX_GPIO_NR(6, 7)//之前的

OK!到此,程序添加成功,下一步就是校准触摸屏了!!!

3、触摸屏的校准

校准的目的:为了与显示屏的坐标一一对应。我们一般采用软件校准,使用Tslib库里的校准软件进行校准们首先需要移植Tslib库。

编译tslib(放到rootfs/tslib/tslib):tar xzf tslib-1.4.tar.gzcd tslib./autogen.sh mkdir tmpecho "ac_cv_func_malloc_0_nonnull=yes" >arm-linux.cache./configure --host=arm-linux --cache-file=arm-linux.cache --prefix=$(pwd)/tmpmakemake install

我的这一部分是放到开发的环境中做的,其实可以直接在单板上搞,如果单板上是有编译器的话。

然后将系统烧写的单板,在单板上操作:

cd /tslib/tslib/tmpcp * / -rfd1.修改 /etc/ts.conf第1行(去掉#号和第一个空格):# module_raw input改为:module_raw input2.export TSLIB_TSDEVICE=/dev/input/event1export TSLIB_CALIBFILE=/etc/pointercalexport TSLIB_CONFFILE=/etc/ts.confexport TSLIB_PLUGINDIR=/lib/tsexport TSLIB_CONSOLEDEVICE=noneexport TSLIB_FBDEVICE=/dev/fb0

测试:

ts_calibrate

ts_test

备注:如果出现段错误,解决办法如下:

1、ts.conf文件中的各个设置选项之前不能有空格,否则会出现: Segmentation fault 错误,

我就不小心在module…之前多了个空格,害我查了好久。

2、不要在pointercal对应的目录下,建立一个空的pointercal文件,否则在运行ts_calibrate时,

也可能会出现Segmentation fault

想一起探讨以及获得各种学习资源加我(有我博客中写的代码的原稿):

qq:1126137994

微信:liu1126137994

可以共同交流关于嵌入式,操作系统,C++语言,C语言,数据结构等技术问题。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。