嵌入式Linux系统之I.MX6触摸屏驱动程序TSC2007.C的分析、移植与校准
2018-03-02 16:18
465 查看
今天来记录一下I.MX6开发板移植触摸屏驱动程序的过程分析。在移植驱动程序之前,为了学习,先去分析一下触摸屏驱动程序的框架。加qq1126137994 一起学习更多技术。
在tsc2007.c文件中初始化tsc2007_init函数注册tsc2007_driver结构体,当tsc2007_driver结构体成员驱动name与平台设备层中name匹配相同时调用tsc2007_probe初始化函数,该函数是tsc2007设备驱动函数的入口。imx6的具体tsc2007设备驱动的实现的主要工作在tsc2007_probe里完成。
下面是分析tsc2007_probe函数的调用关系(并非程序源码,只是列举出关键的函数调用):
当按下触摸板后产生中断,中断里面调用延时函数进入底半部程序。在调度函数里面,先读取坐标,计算压力,然后根据压力大小上报坐标。若触摸板一直按下,那么就重新调用,并通过压力值来看触摸板是否释放。
IMX6的板级初始化函数:Board-mx6q_sabresd.c
由与tsc2007与imx6之间的通信是通过IIC总线进行的,因此在imx6的平台设备层(platform_device)的mx6_sabresd_board_init函数里就需要配置与tsc2007有关的IIC总线。由于是TSC2007所挂的IIC总线是第二根,在平台初始化函数里将会调用i2c_register_board_info函数注册mxc_i2c2_board_info结构体数组。
向mxc_i2c2_board_info结构体数组里添加如下成员:
其中由于TSC2007的A0、A1两个引脚下拉,通过I2C_BOARD_INFO函数注册的从机设备地址是0x48;通过gpio_to_irq函数获取TSC2007中断号,之后会传给平台驱动层,当申请中断会用到;
再构建tsc2007_data_lyy结构体,并添加4个成员:init_platform_hw函数、get_pendown_state函数、irq_pin中断引脚的选择、触摸屏驱动相关参数。
更改中断引脚号:
注:在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函数。这种方式一般放在平台的代码中。
注释:
上面的工作,基本完成了驱动程序的移植,但是后来经过测试,发现显示有错误:
Failed to register i2c client tsc2007 at 0x48 (-16)
Can’t create device at 0x48
一开始以为是i2c总线没有识别到,但是经过调试,发现是中断引脚的复用了。
OK!到此,程序添加成功,下一步就是校准触摸屏了!!!
我的这一部分是放到开发的环境中做的,其实可以直接在单板上搞,如果单板上是有编译器的话。
然后将系统烧写的单板,在单板上操作:
测试:
ts_calibrate
ts_test
备注:如果出现段错误,解决办法如下:
1、ts.conf文件中的各个设置选项之前不能有空格,否则会出现: Segmentation fault 错误,
我就不小心在module…之前多了个空格,害我查了好久。
2、不要在pointercal对应的目录下,建立一个空的pointercal文件,否则在运行ts_calibrate时,
也可能会出现Segmentation fault
想一起探讨以及获得各种学习资源加我(有我博客中写的代码的原稿):
qq:1126137994
微信:liu1126137994
可以共同交流关于嵌入式,操作系统,C++语言,C语言,数据结构等技术问题。
1、tsc2007.c触摸屏驱动程序的分析
I.MX6的触摸屏驱动程序的文件名为:TSC2007.C。在tsc2007.c文件中初始化tsc2007_init函数注册tsc2007_driver结构体,当tsc2007_driver结构体成员驱动name与平台设备层中name匹配相同时调用tsc2007_probe初始化函数,该函数是tsc2007设备驱动函数的入口。imx6的具体tsc2007设备驱动的实现的主要工作在tsc2007_probe里完成。
下面是分析tsc2007_probe函数的调用关系(并非程序源码,只是列举出关键的函数调用):
tsc2007_probe input_dev = input_allocate_device();//(向input核心层申请)分配一个input_dev结构体。 INIT_DELAYED_WORK;//初始化工作队列,把tsc2007工作任务注册到工作队列中,为下面执行队列 的任务作好准备。 tsc2007_work;//通过input_report_abs函数向上层上报触摸屏屏的X、Y坐标和压力值, 执行tsc2007_calculate_pressure函数进行压力校准, init_platform_hw;//? input_set_abs_params;//通过input_dev结构体设置按键和绝对位置事件以及事件下需要处理 的ABS_X、ABS_Y、ABS_PRESSURE的具体事件内容 request_irq(ts->irq, tsc2007_irq, 0, client->dev.driver->name, ts);//为tsc2007中断引脚申请一个中断处理函数, schedule_delayed_work;//中断的上半部分 tsc2007_work; //中断的下半部分, tsc2007_read_values;//读取xy坐标 以及获取压力值 tc->y = tsc2007_xfer(tsc, READ_Y); tc->x = tsc2007_xfer(tsc, READ_X); tsc2007_xfer(tsc, PWRDOWN);//另一次循环测量 rt = tsc2007_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);//上报获取到的值 tsc2007_xfer; data = i2c_smbus_read_word_data; //检测IIC总线的读写操作 val = swab16(data) >> 4; //去掉低4位无效数据(#define MAX_12BIT 由定义知最大为12bit, 所以需要去掉低4位) return val;//tsc2007_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、tsc2007.c触摸屏驱动程序的移植
触摸屏驱动程序的核心部分分析完了,下面就开始移植触摸屏驱动程序,其实,内核自带的驱动程序移植起来非常简单,在理解驱动程序的前提下,在平台设备文件中添加一些私有数据信息,以及配置中断引脚等即可。IMX6的板级初始化函数:Board-mx6q_sabresd.c
由与tsc2007与imx6之间的通信是通过IIC总线进行的,因此在imx6的平台设备层(platform_device)的mx6_sabresd_board_init函数里就需要配置与tsc2007有关的IIC总线。由于是TSC2007所挂的IIC总线是第二根,在平台初始化函数里将会调用i2c_register_board_info函数注册mxc_i2c2_board_info结构体数组。
向mxc_i2c2_board_info结构体数组里添加如下成员:
{ I2C_BOARD_INFO("tsc2007",0x48), .platform_data = (void *)& tsc2007_data_lyy, .irq = gpio_io_irq(SABRESD_TS_INT), }
其中由于TSC2007的A0、A1两个引脚下拉,通过I2C_BOARD_INFO函数注册的从机设备地址是0x48;通过gpio_to_irq函数获取TSC2007中断号,之后会传给平台驱动层,当申请中断会用到;
再构建tsc2007_data_lyy结构体,并添加4个成员:init_platform_hw函数、get_pendown_state函数、irq_pin中断引脚的选择、触摸屏驱动相关参数。
/* * 注意:一下添加的函数,位置没有固定要求,但是为了整齐统一,还是把它放到与其它设备定义的相通的位置,方便以后查看 */ #ifdef CONFIG_TOUCHSCREEN_TSC2007 #include <linux/i2c/tsc2007.h>(在头文件里也添加一下) static int tsc2007_hw_init(void) { int err; err = gpio_request(SABRESD_TS_INT,"tsc2007 irq"); if(err<0) { pr_err("tsc2007 irq gpio request err\n"); return err; } err = gpio_direction_input(SABRESD_TS_INT); if(err<0) { pr_err("tsc2007 irq gpio init input err %d\n",err); gpio_free(SABRESD_TS_INT); return err; } printk("tsc2007 irq gpio init success!\n"); return 0; } static void tsc2007_hw_remove(void) { gpio_free(SABRESD_TS_INT); } static int tsc2007_get_pendown_state(void) { int state; state = gpio_get_value(SABRESD_TS_INT); //printk("tsc2007 get state = %x\n",state); return (state == 0)? 1:0; } static struct tsc2007_platform_data tsc2007_data_lyy= { .model = 2007, .x_plate_ohms =180, .init_platform_hw = tsc2007_hw_init, .exit_platform_hw = tsc2007_hw_remove, .get_pendown_state = tsc2007_get_pendown_state, }; #endif
更改中断引脚号:
将宏SABRESD_TS_INT改为:(之前是3,26) #define SABRESD_TS_INT IMX_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 tsc2007 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的引脚(不然无法识别tsc2007设备) 添加头文件:#define SABRESD_TS_INT IMX_GPIO_NR(6, 7) //lyy 注释掉之前的://#define SABRESD_CAP_TCH_INT1 IMX_GPIO_NR(6, 7)//之前的
OK!到此,程序添加成功,下一步就是校准触摸屏了!!!
3、触摸屏的校准
校准的目的:为了与显示屏的坐标一一对应。我们一般采用软件校准,使用Tslib库里的校准软件进行校准们首先需要移植Tslib库。编译tslib(放到rootfs/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
我的这一部分是放到开发的环境中做的,其实可以直接在单板上搞,如果单板上是有编译器的话。
然后将系统烧写的单板,在单板上操作:
cd /tslib/tslib/tmp cp * / -rfd 1. 修改 /etc/ts.conf第1行(去掉#号和第一个空格): # module_raw input 改为: module_raw input 2. export TSLIB_TSDEVICE=/dev/input/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
ts_test
备注:如果出现段错误,解决办法如下:
1、ts.conf文件中的各个设置选项之前不能有空格,否则会出现: Segmentation fault 错误,
我就不小心在module…之前多了个空格,害我查了好久。
2、不要在pointercal对应的目录下,建立一个空的pointercal文件,否则在运行ts_calibrate时,
也可能会出现Segmentation fault
想一起探讨以及获得各种学习资源加我(有我博客中写的代码的原稿):
qq:1126137994
微信:liu1126137994
可以共同交流关于嵌入式,操作系统,C++语言,C语言,数据结构等技术问题。
相关文章推荐
- 移植Linux系统到iMX6开发板之LVDS显示屏驱动程序的框架分析与移植
- iMX6开发板移植Linux系统之LVDS显示屏驱动程序分析之LVDS参数的匹配过程分析
- 【嵌入式Linux学习七步曲之第三篇 Linux系统bootlaoder移植】U-BOOT全线移植分析系列之二--U-boot基础
- 嵌入式 Linux 系统移植——BSP分析
- linux-2.6.32在mini2440开发板上移植(10)之触摸屏工作原理以及驱动程序详细分析
- linux-2.6.32在mini2440开发板上移植(10)之触摸屏工作原理以及驱动程序详细分析
- linux嵌入式系统开发之触摸屏---驱动篇(下/源码分析)
- #嵌入式Linux最小系统移植# busybox分析和移植记录
- 【嵌入式Linux学习七步曲之第三篇 Linux系统bootlaoder移植】U-BOOT全线移植分析系列之一--BOOTLOADER介绍
- 嵌入式 Linux 系统移植——BSP分析
- 【嵌入式Linux学习七步曲之第三篇 Linux系统bootlaoder移植】U-BOOT全线移植分析系列之二--U-boot基础
- 嵌入式软件开发培训笔记——嵌入式linux内核与文件系统移植与分析
- linux-2.6.32在mini2440开发板上移植(10)之触摸屏工作原理以及驱动程序详细分析
- linux-2.6.32在mini2440开发板上移植---触摸屏工作原理以及驱动程序详细分析
- 【嵌入式Linux学习七步曲之第三篇 Linux系统bootlaoder移植】U-BOOT全线移植分析系列之三--U-BOOT在AT91RM9200上的移植
- 【嵌入式Linux学习七步曲之第三篇 Linux系统bootlaoder移植】U-BOOT全线移植分析系列之一--BOOTLOADER介绍
- 【嵌入式Linux学习七步曲之第三篇 Linux系统bootlaoder移植】U-BOOT全线移植分析系列之三--U-BOOT在AT91RM9200上的移植
- 【嵌入式Linux学习七步曲之第三篇 Linux系统bootlaoder移植】U-BOOT全线移植分析系列之四--U-boot如何引导Linux内核启动?
- 嵌入式Linux系统中的GUI系统的研究与移植
- 嵌入式Linux系统启动过程分析