Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1051010
  • 博文数量: 573
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 66
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-28 16:21
文章分类

全部博文(573)

文章存档

2018年(3)

2016年(48)

2015年(522)

分类: LINUX

2015-12-04 15:54:17

touchsc.c文件

点击(此处)折叠或打开

  1. /*
  2. 触摸屏和LCD是2个不同的物理设备器件,只不过,他们的大小尺寸一样,2个器件叠加在一起
  3. 触摸屏实际上是2层非常薄的电阻膜,距离非常近,稍微按压一下,就会接触到一起。

  4. 触摸屏使用过程:
  5. 1,按下,产生中断(INT_TC中断 : touch change中断,触摸屏的按下,松开,都可以产生INT_TC中断)
  6. 2,在中断处理程序里面,启动AD,转换x,y坐标。
  7. 3,ADC结束,产生ADC中断。
  8. 4,在ADC中断处理程序里面,上报事件,启动定时器。
  9. 5,定时时间到,再次启动ADC。(可以处理滑动,可以处理长按)。
  10. 6,松开。
  11. */
  12. #include <linux/errno.h>
  13. #include <linux/kernel.h>
  14. #include <linux/module.h>
  15. #include <linux/slab.h>
  16. #include <linux/input.h>
  17. #include <linux/init.h>
  18. #include <linux/serio.h>
  19. #include <linux/delay.h>
  20. #include <linux/platform_device.h>
  21. #include <linux/clk.h>
  22. #include <asm/io.h>
  23. #include <asm/irq.h>

  24. #include <plat/regs-adc.h>
  25. #include <mach/regs-gpio.h>

  26. /* 触摸屏相关的寄存器
  27. 写成结构体的原因是:一次内存映射所有的寄存器。
  28.  */
  29. struct s3c_ts_regs
  30. {
  31.     unsigned long adccon; /*0x58000000*/
  32.     unsigned long adctsc;
  33.     unsigned long adcdly;
  34.     unsigned long adcdat0;
  35.     unsigned long adcdat1;
  36.     unsigned long adcupdn;
  37. };

  38. static volatile struct s3c_ts_regs * sc_regs;
  39. static struct input_dev * sc_dev;        /*定义一个input设备*/
  40. static struct clk *sc_clock;
  41. static int noused = 0;

  42. static struct timer_list sc_timer;    /*内核定时器*/

  43. /*函数功能 : 进入(等待触摸屏按下)中断模式
  44. 触摸屏控制器有4种工作模式 :
  45. 1,等待中断模式(按下/松开)
  46. 2,分离的x/y轴坐标转换模式。
  47. 3,自动x/y轴坐标转换模式。
  48. 4,普通转换模式。
  49. */
  50. static void enter_wait_pen_down_mode(void)
  51. {
  52.         sc_regs->adctsc = 0xd3;
  53. }

  54. /*函数功能 : 进入(等待触摸屏松开)中断模式*/
  55. static void enter_wait_pen_up_mode(void)
  56. {
  57.         sc_regs->adctsc = 0x1d3;
  58. }

  59. /*函数功能 : 进入(自动x/y轴坐标转换)模式*/
  60. static void enter_measure_xy_mode(void)
  61. {
  62.         sc_regs->adctsc = (1<<3)|(1<<2);
  63. }

  64. /*函数功能 : 启动AD转换
  65. 注意 : AD转换不可能瞬间完成,本程序不使用查询方式来等待AD转换完毕,使用中断方式来等待AD转换完毕。
  66. */
  67. static void start_adc(void)
  68. {
  69.         sc_regs->adccon |= (1<<0);
  70. }

  71. /*函数功能 : 禁止AD转换*/
  72. static void disable_adc(void)
  73. {
  74.         sc_regs->adccon &= (~(1<<0));
  75. }

  76. /*函数功能 : 软件过滤
  77. 策略 : 如果4个值中,有1个值偏离其他3个值很多,则这组数据的4个值全部丢弃。重新采样
  78. 分析4个采样值的一种策略而已,策略比较粗糙,可以设计出更好的。
  79. 返回值 : 0:过滤成功,4个值都是正常的 -1:过滤失败,4个值中有1或者几个偏离很多
  80. 注意 : 加入这个策略之后,就会出现按压触摸屏的时候,没有坐标值打印出来,需要重新按压触摸屏。
  81. */
  82. static int filter_sc(int x[], int y[])
  83. {
  84. #define ERR_LIMIT 10 /*这个值只是一个经验值,可以通过观察来修改这个值*/

  85.     int avr_x, avr_y;        /*平均值*/
  86.     int det_x, det_y;        /*误差值*/

  87.     avr_x = (x[0] + x[1])/2;
  88.     avr_y = (y[0] + y[1])/2;

  89.     det_x = (x[2] > avr_x) ? (x[2] - avr_x) : (avr_x - x[2]);
  90.     det_y = (y[2] > avr_y) ? (y[2] - avr_y) : (avr_y - y[2]);

  91.     if((det_x > ERR_LIMIT) || (det_y > ERR_LIMIT)) /*滤掉一个数据*/
  92.     {
  93.             return -1;
  94.     }

  95.     avr_x = (x[1] + x[2])/2;
  96.     avr_y = (y[1] + y[2])/2;

  97.     det_x = (x[3] > avr_x) ? (x[3] - avr_x) : (avr_x - x[3]);
  98.     det_y = (y[3] > avr_y) ? (y[3] - avr_y) : (avr_y - y[3]);

  99.     if((det_x > ERR_LIMIT) || (det_y > ERR_LIMIT))
  100.     {
  101.             return -1;
  102.     }
  103.     
  104.     avr_x = (x[2] + x[3])/2;
  105.     avr_y = (y[2] + y[3])/2;

  106.     det_x = (x[0] > avr_x) ? (x[0] - avr_x) : (avr_x - x[0]);
  107.     det_y = (y[0] > avr_y) ? (y[0] - avr_y) : (avr_y - y[0]);

  108.     if((det_x > ERR_LIMIT) || (det_y > ERR_LIMIT))
  109.     {
  110.             return -1;
  111.     }

  112.     return 0; /*全部经过了过滤*/
  113. }

  114. /*INT_TC 中断处理函数 :
  115. 当触摸笔按下 或者 松开的时候,产生中断(INT_TC中断 : touch change中断,触摸屏的按下,松开,都可以产生INT_TC中断)
  116. 就会触发执行下面的 函数 pen_down_up_interrupt。
  117. */
  118. static irqreturn_t pen_down_up_interrupt(int irq, void *dev_id)
  119. {
  120.         //printk("DRIVER: sc_regs->adcdat0=[0x%x]\n", (unsigned int)(sc_regs->adcdat0));

  121.         if(sc_regs->adcdat0 & (1<<15))    /*松开*/
  122.         {
  123.                 //printk("DRIVER : pen up\n");
  124.                 
  125.                 input_report_abs(sc_dev, ABS_PRESSURE, 0);    /*上报压力方向事件 0: 松开*/
  126.                 input_report_key(sc_dev, BTN_TOUCH, 0); /*上报触摸事件 0: 松开*/
  127.                 input_sync(sc_dev);
  128.                 
  129.                 enter_wait_pen_down_mode();            /*松开状态时 : 则进入(等待触摸屏按下)中断模式*/
  130.         }
  131.         else /*按下*/
  132.         {
  133.                 //printk("DRIVER : pen down\n");
  134.                 //enter_pen_up_mode();            /*按下状态时 : 则进入(等待触摸屏松开)中断模式*/
  135.                 enter_measure_xy_mode();        /*进入(自动x/y轴坐标转换)模式*/
  136.                 start_adc();                                /*启动AD转换*/
  137.                 //printk("DRIVER: start_adc ok\n");
  138.         }

  139.         return IRQ_HANDLED;
  140. }

  141. /*INT_ADC_S 中断处理函数 :
  142. 当AD转换完毕的时候,产生INT_ADC_S中断。
  143. 就会触发执行下面的 函数 adc_interrupt。
  144. */
  145. static irqreturn_t adc_interrupt(int irq, void *dev_id)
  146. {
  147.         int ret = -1;
  148.         
  149.         static int count = 0;
  150.         /*多次测量,取平均值,这里保存多次测量的结果*/
  151.         static int x[4];
  152.         static int y[4];

  153.         int x_data;
  154.         int y_data;

  155.         //printk("DRIVER : adc_interrupt\n");
  156.         //走到这里,说明触摸屏的xy轴坐标转换完毕
  157.     
  158.         /*优化措施2 : 如果ADC完成时,发现触摸笔已经松开,则丢弃此次结果*/
  159.         if(sc_regs->adcdat0 & (1<<15))    /*如果已经松开,丢弃结果*/
  160.         {
  161.                 //printk("DRIVER : adc_interrupt up\n");
  162.                 count = 0;
  163.                 
  164.                 /*松开上报事件,其实只放这里一处就行,多放也没有关系*/
  165.                 input_report_abs(sc_dev, ABS_PRESSURE, 0);    /*上报压力方向事件 0: 松开*/
  166.                 input_report_key(sc_dev, BTN_TOUCH, 0); /*上报触摸事件 0: 松开*/
  167.                 input_sync(sc_dev);
  168.                 
  169.                 enter_wait_pen_down_mode();            /*进入(等待触摸屏按下)中断模式*/
  170.         }
  171.         else /*如果还是按下,则取得这次转换后的结果*/
  172.         {
  173.                 /* 优化措施3: 多次测量求平均值 */
  174.                 x[count] = (sc_regs->adcdat0) & 0x3ff;
  175.                 y[count] = (sc_regs->adcdat1) & 0x3ff;
  176.                 ++count;
  177.                 if(count == 4) /*同一个点,连续测量4次,再计算平均值*/
  178.                 {
  179.                         /*优化措施4 : 软件过滤*/
  180.                         ret = filter_sc(x, y);
  181.                         if(ret == 0) /*过滤成功:才使用这4个值来求平均值*/
  182.                         {
  183.                                 x_data = x[0]/4+x[1]/4+x[2]/4+x[3]/4;
  184.                                 y_data = y[0]/4+y[1]/4+y[2]/4+y[3]/4;
  185.                                 printk("x=[%d], y=[%d]\n", x_data, y_data);

  186.                                 /*得到最终的坐标结果之后,就可以把打印的地方变成上报事件了。
  187.                                 input_report_abs实际就是input_event函数的封装*/
  188.                                 input_report_abs(sc_dev, ABS_X, x_data);        /*上报x方向的位移值*/
  189.                                 input_report_abs(sc_dev, ABS_Y, y_data);        /*上报y方向的位移值*/
  190.                                 input_report_abs(sc_dev, ABS_PRESSURE, 1);    /*上报压力方向事件 1: 按下*/
  191.                                 input_report_key(sc_dev, BTN_TOUCH, 1); /*上报触摸事件 1: 按下*/
  192.                                 input_sync(sc_dev);
  193.                         }
  194.                         /*过滤失败:丢弃这4个值,重新测量*/
  195.                         count = 0;
  196.                         enter_wait_pen_up_mode();            /*进入(等待触摸屏松开)中断模式*/

  197.                         /* 启动定时器处理长按/滑动的情况 */
  198.         
  199.                         /* 修改定时器定时时间,定时10ms,即10ms秒后执行定时器函数keys_timer_function ,
  200.                         使用这个定时器的目的是 : 处理长按/滑动。这里HZ/100即定时10ms
  201.                         */
  202.                         mod_timer(&sc_timer, jiffies+HZ/100);
  203.                 }
  204.                 else /*再次测量*/
  205.                 {
  206.                         enter_measure_xy_mode();        /*进入(自动x/y轴坐标转换)模式*/
  207.                         start_adc();                                /*启动AD转换*/
  208.                 }
  209.         }
  210.         return IRQ_HANDLED;
  211. }

  212. /*
  213. 函数功能 : 相当于是每10ms,连续进行AD转换
  214. */
  215. static void sc_timer_function(unsigned long data)
  216. {
  217.         if(sc_regs->adcdat0 & (1<<15))    /*10ms后,如果已经松开,丢弃结果*/
  218.         {
  219.                 input_report_abs(sc_dev, ABS_PRESSURE, 0);    /*上报压力方向事件 0: 松开*/
  220.                 input_report_key(sc_dev, BTN_TOUCH, 0); /*上报触摸事件 0: 松开*/
  221.                 input_sync(sc_dev);

  222.                 enter_wait_pen_down_mode();            /*进入(等待触摸屏按下)中断模式*/
  223.         }
  224.         else /*如果还是按下,则取得这次转换后的结果*/
  225.         {
  226.                 enter_measure_xy_mode();        /*进入(自动x/y轴坐标转换)模式*/
  227.                 start_adc();                                /*启动AD转换*/
  228.         }
  229. }

  230. static int __init sc_init(void)
  231. {
  232.         unsigned int ret = 0;

  233.         /* 1,分配一个input_dev结构体 */
  234.         sc_dev = (struct input_dev*)input_allocate_device();
  235.         /*input_allocate_device()函数在内存中为输入设备结构体分配一个空间,并对其主要的成员进行了初始化. */
  236.         if(sc_dev == NULL)
  237.         {
  238.                 printk("DEVICE: input_allocate_device err\n");
  239.                 ret = -ENOMEM;
  240.         }

  241.         /* 2,设置 */
  242.         /* 2.1 设置能产生哪类事件 evbit : 表示能产生哪类事件 */
  243.         set_bit(EV_KEY, sc_dev->evbit);                    /*EV_KEY : 表示能产生按键类事件。*/
  244.         set_bit(EV_ABS, sc_dev->evbit);                    /*EV_ABS : 表示能产生绝对位移事件。俗称手势*/

  245.         /* 2.2.1 设置能产生按键类操作的哪些事件 keybit : 表示能产生哪些按键事件 */
  246.         set_bit(BTN_TOUCH, sc_dev->keybit);                /*BTN_TOUCH : 表示触摸事件*/

  247.         /* 2.2.2 设置能产生绝对位移操作的哪些事件*/
  248.         input_set_abs_params(sc_dev, ABS_X, 0, 0x3FF, 0, 0);        /*ABS_X : x方向的位移,0x3FF表示是AD的10位分辨率,看数据手册可知*/
  249.         input_set_abs_params(sc_dev, ABS_Y, 0, 0x3FF, 0, 0);        /*ABS_Y : y方向的位移,0x3FF表示是AD的10位分辨率,看数据手册可知*/
  250.         input_set_abs_params(sc_dev, ABS_PRESSURE, 0, 1, 0, 0);    /*ABS_PRESSURE : 压力方向*/

  251.         /* 3,注册一个输入设备 : 加入输入设备的链表中*/
  252.         input_register_device((struct input_dev *)sc_dev);

  253.         /* 4,硬件相关的操作 : 注册中断 */
  254.         /* 4.1,使能时钟 */
  255.         sc_clock = clk_get(NULL, "adc");
  256.         clk_enable(sc_clock);                            /*使能时钟(CLKCON[15])*/

  257.         /* 4.2 设置S3C2440的ADC/TS寄存器 */
  258.         sc_regs = ioremap(0x58000000, sizeof(struct s3c_ts_regs));
  259.         if(sc_regs == NULL)
  260.         {
  261.             printk("DEVICE:ioremap() sc_regs err!\n");
  262.             return -1;
  263.         }

  264.         printk("DEVICE:ioremap() sc_regs ok! &adccon=[%p]\n", &(sc_regs->adccon));
  265.         printk("DEVICE:ioremap() sc_regs ok! &adctsc=[%p]\n", &(sc_regs->adctsc));
  266.         printk("DEVICE:ioremap() sc_regs ok! &adcdly=[%p]\n", &(sc_regs->adcdly));
  267.         printk("DEVICE:ioremap() sc_regs ok! &adcdat0=[%p]\n", &(sc_regs->adcdat0));
  268.         printk("DEVICE:ioremap() sc_regs ok! &adcdat1=[%p]\n", &(sc_regs->adcdat1));
  269.         printk("DEVICE:ioremap() sc_regs ok! &adcupdn=[%p]\n", &(sc_regs->adcupdn));

  270.         /*由dmesg命令,打印出来的信息,可知 : PCLH 的值 是50MHZ
  271.         S3C244X: core 400.000 MHz, memory 100.000 MHz, peripheral 50.000 MHz
  272.         预分频值取49时,AD时钟是1M。*/
  273.         sc_regs->adccon = (1<<14)|(49<<6);
  274.         disable_adc(); /*初始化时,并不启动AD转换*/

  275.         /*注册 INT_TC 中断 : 按下 或者 松开时,产生中断*/
  276.         ret = request_irq(IRQ_TC, pen_down_up_interrupt, IRQF_SAMPLE_RANDOM, "tc_pen", NULL);
  277.         if(ret != 0)
  278.         {
  279.                 printk("DEVICE: request_irq IRQ_TC :[%d],[%d]!\n", EIO, ret);
  280.                 iounmap(sc_regs);
  281.                 return -EIO;
  282.         }

  283.         /*注册 INT_ADC_S 中断 : AD转换完毕,产生中断*/
  284.         ret = request_irq(IRQ_ADC, adc_interrupt, IRQF_SHARED|IRQF_SAMPLE_RANDOM, "myadc", &noused);
  285.         if(ret != 0)
  286.         {
  287.                 printk("DEVICE: request_irq IRQ_ADC :[%d],[%d]!\n", EIO, ret);
  288.                 iounmap(sc_regs);
  289.                 return -EIO;
  290.         }

  291.         /*现在是刚按下,就产生INT_TC 中断,可能采样的电压还没有稳定,所以需要
  292.         优化措施1 : 设置延迟采样时间为最大值。这样可以采样到稳定后的电压,这之后产生的中断才是我们想要的。*/
  293.         sc_regs->adcdly = 0xffff; /*大概是15ms时间*/

  294.         /* 优化措施5: 使用定时器处理长按,滑动的情况*/
  295.         init_timer(&sc_timer);
  296.         sc_timer.function = sc_timer_function;
  297.         add_timer(&sc_timer); /*激活定时器 IRQT_BOTHEDGE*/

  298.         enter_wait_pen_down_mode(); //进入(等待触摸屏按下)中断模式
  299.         
  300.         printk("DEVICE: sc_init ok\n");

  301.         return 0;
  302. }

  303. static void __exit sc_exit(void)
  304. {
  305.         del_timer(&sc_timer);
  306.     
  307.         disable_irq(IRQ_ADC);
  308.         disable_irq(IRQ_TC);
  309.         free_irq(IRQ_TC, NULL);
  310.         free_irq(IRQ_ADC, &noused);

  311.         iounmap(sc_regs);

  312.         //禁止时钟,下面3句是一起出来的
  313.         clk_disable(sc_clock);
  314.         clk_put(sc_clock);
  315.         sc_clock = NULL;

  316.         input_unregister_device(sc_dev);
  317.         input_free_device(sc_dev);
  318. }

  319. module_init(sc_init);
  320. module_exit(sc_exit);

  321. MODULE_AUTHOR("wangxiancai"); //代码的作者
  322. MODULE_DESCRIPTION("touchsc driver"); //代码的描述,功能
  323. MODULE_LICENSE("GPL"); //开源协议
  324. MODULE_ALIAS("input:touchsc");



  325. /*
  326. 编译:
  327. 遇到申请中断返回ret=-22 : 多半是在申请的时候使用了IRQF_SAMPLE_RANDOM标志,
  328. 却在dev_id这个参数传递了NULL吧。解决方法非常简单,只需要把这个参数设为非空即可,
  329. 因为如果IRQF_SHARED的话,中断机制需要将dev_id传递给Handler.如果实在不需要这个参数的话,
  330. 就按照如下处理就行:

  331. 遇到申请中断返回ret=-16 : 表示中断已经被使用,要不你设置成共享中断试试看
  332. static int noused;
  333. request_irq(...., &noused);

  334. 注意 : 因为 IRQ_ADC中断已经有人申请了,# cat /proc/interrupts可知,所以使用IRQF_SHARED,
  335. 并且每次修改本文件的驱动代码,都要reboot; tftp 0x32000000; bootm一下内核。
  336. 仅仅只做 # rmmod touchsc.ko是不够的。

  337. 测试 :
  338. 1,make menuconfig 去掉触摸屏的驱动
  339. Device Drivers --->
  340.         Input device support --->
  341.                 [*] Touchscreens --->
  342.                         <*> EmbedSky TQ2440 TouchScreen input driver //这里去掉*
  343. # make clean;make

  344. 2,第一种,不校验的测试方法,也可以使用以前做裸机驱动程序时候,固定的校验公式。
  345. # ls -lrt /dev/event* //什么也没有
  346. # insmod touchsc.ko
  347. # ls -lrt /dev/event*
  348. crw-rw---- 1 root root 13, 64 Jan 1 00:01 /dev/event0
  349. # hexdump /dev/event0 //把文件里面的值,按照16进制的格式显示出来。

  350.            秒 微秒 type code value
  351. 0000000 00ad 0000 7017 0000 0003 0000 019e 0000

  352. //#define EV_ABS            0x03            //绝对位移事件, 上面的类型3,就是产生的事件类型
  353. //#define EV_KEY            0x01 //按键类事件
  354. //#define ABS_X            0x00                //绝对位移事件中的 x方向绝对位移事件
  355. //#define ABS_Y            0x01                //绝对位移事件中的 y方向绝对位移事件
  356. //#define ABS_PRESSURE        0x18 //绝对位移事件中的 压力方向事件
  357. //#define BTN_TOUCH        0x14a            //按键类事件中的 触摸事件

  358. x=[414], y=[280] //这个是驱动程序打印出来的,下面是 /dev/event0文件中的数据
  359. 0000000 00ad 0000 7017 0000 0003 0000 019e 0000     //type=3,表示是绝对位移; code=0,表示是x方向; value=019e,表示x=[414]=019e;
  360. 0000010 00ad 0000 7045 0000 0003 0001 0118 0000        //type=3,表示是绝对位移; code=1,表示是y方向; value=0118,表示y=[280]=0118;
  361. 0000020 00ad 0000 704b 0000 0003 0018 0001 0000 //type=3,表示是绝对位移; code=18,表示是压力; value=0001,表示有压按
  362. 0000030 00ad 0000 7051 0000 0001 014a 0001 0000 //type=1,表示是按键,code=014a,表示是触摸; value=0001,表示有触摸
  363. 0000040 00ad 0000 7057 0000 0000 0000 0000 0000        //type=0,表示同步事件

  364. x=[404], y=[283]
  365. 0000050 00ad 0000 00d4 0001 0003 0000 0194 0000
  366. 0000060 00ad 0000 00f4 0001 0003 0001 011b 0000
  367. 0000070 00ad 0000 0102 0001 0000 0000 0000 0000
  368. 0000080 00ad 0000 2519 0001 0003 0018 0000 0000
  369. 0000090 00ad 0000 2545 0001 0001 014a 0000 0000
  370. 00000a0 00ad 0000 2547 0001 0000 0000 0000 0000
  371. 注意 : 因为还没有校验,所以这里打印的坐标,不是正常的LCD坐标
  372. */

  373. /*
  374. 第2种,需要校验的测试方法:
  375. 原理 : 驱动程序已经完成,触摸屏发生按下,长按,滑动事件的时候,
  376. 驱动设备文件 /dev/event0 中会记录下所有的 事件,所有触点的坐标也会记录下来
  377. 所以,应用程序可以取得所有相关的值,但是值还不能直接使用,还需要校验

  378. 1, ubuntu必须联网,安装下面的3个工具
  379. 在ubuntu的CRT目录下:
  380. # sudo apt-get install autoconf
  381. # sudo apt-get install automake
  382. # sudo apt-get install libtool

  383. 2,解压文件:
  384. # cd /home/wangxc/linux/rootfs/nfs_2.6.30/wxc/app/touchscreen //这个是nfs文件系统的目录
  385. //其中/wxc就是开发板根目录
  386. # ls -lrt
  387.     -rwxrwxrwx 1 nobody nogroup 60336 Jan 20 2011 tslib-1.4.tar.gz
  388. # tar xzf tslib-1.4.tar.gz //解压触摸屏的应用程序
  389. # ls -lrt
  390.     -rwxrwxrwx 1 nobody nogroup 60336 Jan 20 2011 tslib-1.4.tar.gz
  391.     drwxrwxrwx 10 wangxc wangxc 4096 Apr 7 07:00 tslib
  392. # cd tslib

  393. 3,生成makefile文件:
  394. # ./autogen.sh //上面的 autoconf automake libtool 必须安装过了,否则这里会报错

  395. # mkdir tmp
  396. # echo "ac_cv_func_malloc_0_nonnull=yes" >arm-linux.cache

  397. # export PATH=$PATH:/home/wangxc/linux/toolchain/crosstools_4.4.3_softfloat/bin
  398.     
  399. //# ./configure --host=arm-linux --cache-file=arm-linux.cache --enable-inputapi=no -prefix=$(pwd)/tmp

  400. 使用下面这个就可以了
  401. # ./configure --host=arm-linux --cache-file=arm-linux.cache --prefix=$(pwd)/tmp

  402. 4,编译
  403. # make
  404. # make install //编译的结果,都会安装到tmp临时目录里面

  405. 5,安装:
  406. # cd tmp
  407. # cp * -rfd /wxc/app/touchscreen //带链接脚本的,拷贝到开发板的根目录中
  408. //已经在这个目录下面解压的,所以不需要安装,可以在PATH中加入/tmp/bin目录的路径

  409. 6,修改 /etc/ts.conf第1行(去掉#号和第一个空格)
  410. # module_raw input
  411. 改为:
  412. module_raw input

  413. 7,使用:
  414. 在serial CRT开发板目录下,先安装s3c_ts.ko, lcd.ko
  415. # cd /wxc/driver/chardriver/ko
  416. # ls -lrt /dev/fb* //没有文件
  417. # insmod cfbfillrect.ko //只是提供一些函数,它们本身并不是驱动程序。
  418. # insmod cfbcopyarea.ko
  419. # insmod cfbimgblt.ko
  420. # insmod lcd.ko //使用自己编写的LCD驱动程序
  421. # ls -lrt /dev/fb* //有fb0文件
  422. crw-rw---- 1 root root 29, 0 Jan 1 00:00 /dev/fb0 //LCD可用,一定有这个文件

  423. # ls -lrt /dev/event* //没有event0文件
  424. # insmod touchsc.ko
  425. # ls -lrt /dev/event* //有event0文件
  426. crw-rw---- 1 root root 13, 64 Jan 1 00:18 /dev/event0 //触摸屏可用,一定有这个文件

  427. 8.配置触摸屏识别的环境
  428. //触摸屏程序 ts_test 打开哪些文件,通过下面的环境变量来设置
  429. # export TSLIB_TSDEVICE=/dev/event0 //触摸屏文件
  430. # export TSLIB_CALIBFILE=/etc/pointercal //校验文件存放目录
  431. # export TSLIB_CONFFILE=/etc/ts.conf //配置文件存放路径
  432. //# export TSLIB_CONFFILE=/wxc/app/touchscreen/tslib/tmp/etc/ts.conf
  433. # export TSLIB_PLUGINDIR=/lib/ts //插件放在这里
  434. //# export TSLIB_PLUGINDIR=/wxc/app/touchscreen/tslib/tmp/lib/ts
  435. # export TSLIB_CONSOLEDEVICE=none                 //
  436. # export TSLIB_FBDEVICE=/dev/fb0 //LCD文件,是这个吗?

  437. //************************************************ 只用这个就可以了
  438. export TSLIB_TSDEVICE=/dev/event0
  439. export TSLIB_CALIBFILE=/etc/pointercal
  440. export TSLIB_CONFFILE=/wxc/app/charapp/touchscreen/tslib/tmp/etc/ts.conf
  441. export TSLIB_PLUGINDIR=/lib/ts
  442. export TSLIB_PLUGINDIR=/wxc/app/charapp/touchscreen/tslib/tmp/lib/ts
  443. export TSLIB_CONSOLEDEVICE=none
  444. export TSLIB_FBDEVICE=/dev/fb0
  445. //************************************************

  446. 9,触摸屏校验
  447. # export PATH=$PATH:/wxc/app/charapp/touchscreen/tslib/tmp/bin
  448. 上面也可以不用 export
  449. 进入到上面的bin目录就行了
  450. # cd /wxc/app/touchscreen/tslib/tmp/bin
  451. # ts_calibrate //校验
  452. //我走到这里,如果在屏幕上没有文字,左上角为什么没有十字架:说明LCD驱动没有生效。
  453. 注意 : 校验成功之后,可以看见,serial通过CRT打印出来的坐标是正常的LCD屏幕坐标

  454. 10,绘图开始
  455. # ts_test //可以支持手写
  456. # ls -lrt /etc/pointercal
  457. */
makefile文件

点击(此处)折叠或打开

  1. # File: Makefile
  2. # wangxiancai

  3. MODEXT = ko
  4. # INSTALLDIR=/home/wangxc/linux/rootfs/nfs_2.6.13/wxc/driver/chardriver/ko
  5. INSTALLDIR=/home/wangxc/linux/rootfs/nfs_2.6.30/wxc/driver/chardriver/ko
  6. # CROSS=/home/wangxc/linux/toolchain/crosstools_3.4.1_softfloat/arm-linux/gcc-3.4.1-glibc-2.3.3/bin/arm-linux-
  7. CROSS=/home/wangxc/linux/toolchain/crosstools_4.4.3_softfloat/bin/arm-linux-
  8. # KERNELDIR=/home/wangxc/linux/kernel/kernel-2.6.13
  9. KERNELDIR=/home/wangxc/linux/kernel/kerner-2.6.30

  10. CC= $(CROSS)gcc
  11. LD= $(CROSS)ld

  12. #############################################################################
  13. # Compiler Flags
  14. #############################################################################
  15. EXTRA_CFLAGS += -I$(KERNELDIR)/include
  16. #############################################################################
  17. # Make Targets
  18. #############################################################################
  19. obj-m := touchsc.o
  20. default:
  21.     $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
  22. # Otherwise we were called directly from the command line; invoke the kernel build system.

  23. install: default
  24.     rm -rf $(INSTALLDIR)/touchsc.$(MODEXT)
  25.     cp -rf $(PWD)/touchsc.$(MODEXT) $(INSTALLDIR)

  26. clean:
  27.     rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.bak modules.order Module.symvers

阅读(1063) | 评论(0) | 转发(0) |
0

上一篇:linux LCD驱动

下一篇:nandflash驱动

给主人留下些什么吧!~~