嵌入式驱动移植之触摸驱动初识

发布者:心怀感恩最新更新时间:2021-07-23 来源: eefocus关键字:嵌入式驱动  移植  触摸驱动 手机看文章 扫描二维码
随时随地手机看文章

开发环境

BootLoader:u-boot-1.1.6

kernel:linux-2.6.30.4

CPU:s3c2440

开发板:TQ2440

参考资料:《天嵌科技Linux移植手册》


移植步骤

1、触摸驱动编写

此处直接用天嵌提供的源码,从天嵌科技提供的 2.6.30.4 的源码中的“drivers/input/touchsreen/”拷贝“tq2440_ts.c”文件到我的内核的“drivers/input/touchsreen/”目录下,然后修改驱动源码的 41 行为如下内容:


//extern struct semaphore ADC_LOCK; //这个原来的内容

DECLARE_MUTEX(ADC_LOCK); //这是修改后的内容


说明:修改原因,因为天嵌科技提供的触摸驱动中使用了 ADC 驱动中的 ADC_LOCK,而这里并没有移植 ADC 驱动,所以这里做一下简单的改变。

源代码如下:


#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include


#include

#include


/* For ts.dev.id.version */

#define S3C2410TSVERSION 0x0101


#define WAIT4INT(x)  (((x)<<8) |

     S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN |

     S3C2410_ADCTSC_XY_PST(3))


#define AUTOPST      (S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN |

     S3C2410_ADCTSC_AUTO_PST | S3C2410_ADCTSC_XY_PST(0))


static char *tq2440ts_name = "TQ2440 TouchScreen";


static struct input_dev *dev;

static long xp;

static long yp;

static int count;


extern struct semaphore ADC_LOCK;

static int OwnADC = 0;


static void __iomem *base_addr;

/*

static inline void tq2440_ts_connect(void)

{

s3c2410_gpio_cfgpin(S3C2410_GPG12, S3C2410_GPG12_XMON);

s3c2410_gpio_cfgpin(S3C2410_GPG13, S3C2410_GPG13_nXPON);

s3c2410_gpio_cfgpin(S3C2410_GPG14, S3C2410_GPG14_YMON);

s3c2410_gpio_cfgpin(S3C2410_GPG15, S3C2410_GPG15_nYPON);

}

*/

static void touch_timer_fire(unsigned long data)

{

  unsigned long data0;

  unsigned long data1;

int updown;


  data0 = ioread32(base_addr+S3C2410_ADCDAT0);

  data1 = ioread32(base_addr+S3C2410_ADCDAT1);


  updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));


  if (updown) {

  if (count != 0)

  {

long tmp;

                                                                                                 

tmp = xp;

xp = yp;

yp = tmp;

                                                                                                 

                        xp >>= 2;

                        yp >>= 2;


  input_report_abs(dev, ABS_X, xp);

  input_report_abs(dev, ABS_Y, yp);


  input_report_key(dev, BTN_TOUCH, 1);

input_report_abs(dev, ABS_PRESSURE, 1);

  input_sync(dev);

  }


  xp = 0;

  yp = 0;

  count = 0;


  iowrite32(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);

  iowrite32(ioread32(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);

  }

  else

  {

  count = 0;


  input_report_key(dev, BTN_TOUCH, 0);

  input_report_abs(dev, ABS_PRESSURE, 0);

  input_sync(dev);


  iowrite32(WAIT4INT(0), base_addr+S3C2410_ADCTSC);

if (OwnADC)

{

OwnADC = 0;

up(&ADC_LOCK);

}

  }

}


static struct timer_list touch_timer =

TIMER_INITIALIZER(touch_timer_fire, 0, 0);


static irqreturn_t stylus_updown(int irq, void *dev_id)

{

unsigned long data0;

unsigned long data1;

int updown;


if (down_trylock(&ADC_LOCK) == 0)

{

OwnADC = 1;

data0 = ioread32(base_addr+S3C2410_ADCDAT0);

data1 = ioread32(base_addr+S3C2410_ADCDAT1);


updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));


if (updown)

{

touch_timer_fire(0);

}

else

{

OwnADC = 0;

up(&ADC_LOCK);

}

}


return IRQ_HANDLED;

}



static irqreturn_t stylus_action(int irq, void *dev_id)

{

unsigned long data0;

unsigned long data1;


if (OwnADC)

{

data0 = ioread32(base_addr+S3C2410_ADCDAT0);

data1 = ioread32(base_addr+S3C2410_ADCDAT1);


xp += data0 & S3C2410_ADCDAT0_XPDATA_MASK;

yp += data1 & S3C2410_ADCDAT1_YPDATA_MASK;

count++;


if (count < (1<<2))

{

iowrite32(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);

iowrite32(ioread32(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);

}

else

{

mod_timer(&touch_timer, jiffies+1);

iowrite32(WAIT4INT(1), base_addr+S3C2410_ADCTSC);

}

}


return IRQ_HANDLED;

}


static struct clk *adc_clock;


static int __init tq2440ts_init(void)

{

struct input_dev *input_dev;


adc_clock = clk_get(NULL, "adc");

if (!adc_clock)

{

printk(KERN_ERR "failed to get adc clock sourcen");

return -ENOENT;

}

clk_enable(adc_clock);


base_addr=ioremap(S3C2410_PA_ADC,0x20);

if (base_addr == NULL)

{

printk(KERN_ERR "Failed to remap register blockn");

return -ENOMEM;

}


/* Configure GPIOs */

// tq2440_ts_connect();


iowrite32(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(0xFF),base_addr+S3C2410_ADCCON);

iowrite32(0xffff,  base_addr+S3C2410_ADCDLY);

iowrite32(WAIT4INT(0), base_addr+S3C2410_ADCTSC);


/* Initialise input stuff */

input_dev = input_allocate_device();


if (!input_dev)

{

printk(KERN_ERR "Unable to allocate the input device !!n");

return -ENOMEM;

}


dev = input_dev;

dev->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS);

dev->keybit[BITS_TO_LONGS(BTN_TOUCH)] = BIT(BTN_TOUCH);

input_set_abs_params(dev, ABS_X, 0, 0x3FF, 0, 0);

input_set_abs_params(dev, ABS_Y, 0, 0x3FF, 0, 0);

input_set_abs_params(dev, ABS_PRESSURE, 0, 1, 0, 0);


dev->name = tq2440ts_name;

dev->id.bustype = BUS_RS232;

dev->id.vendor = 0xDEAD;

dev->id.product = 0xBEEF;

dev->id.version = S3C2410TSVERSION;


if (request_irq(IRQ_ADC, stylus_action, IRQF_SHARED|IRQF_SAMPLE_RANDOM, tq2440ts_name, dev))

{

printk(KERN_ERR "tq2440_ts.c: Could not allocate ts IRQ_ADC !n");

iounmap(base_addr);

return -EIO;

}

if (request_irq(IRQ_TC, stylus_updown, IRQF_SAMPLE_RANDOM, tq2440ts_name, dev))

{

printk(KERN_ERR "tq2440_ts.c: Could not allocate ts IRQ_ADC !n");

iounmap(base_addr);

return -EIO;

}


printk(KERN_INFO "%s successfully loadedn", tq2440ts_name);


input_register_device(dev);


return 0;

}


static void __exit tq2440ts_exit(void)

{

disable_irq(IRQ_ADC);

disable_irq(IRQ_TC);

free_irq(IRQ_TC,dev);

free_irq(IRQ_ADC,dev);


if (adc_clock)

{

clk_disable(adc_clock);

clk_put(adc_clock);

adc_clock = NULL;

}


input_unregister_device(dev);

iounmap(base_addr);

}



module_init(tq2440ts_init);

module_exit(tq2440ts_exit);


其实就是将此驱动程序编译进内核中,使内核支持触摸功能,可以采用编译成模块,加载进内核的方式,也可以直接编译进内核。此处采用第二种方式。

修改同目录下的“Kconfig”和“Makefile”文件。

在 Kconfig 文件的 468 行添加如下内容:


config TOUCHSCREEN_TQ2440

tristate "EmbedSky TQ2440 TouchScreen input driver"

depends on ARCH_S3C2410 && INPUT && INPUT_TOUCHSCREEN

help

Say Y here if you have the TQ2440 TouchScreen.

and depends on TQ2440_ADC

If unsure, say N.

To compile this driver as a module, choose M here: the

module will be called tq2440_ts.


在 Makefile 文件的最后添加如下内容:


obj-$(CONFIG_TOUCHSCREEN_TQ2440) += tq2440_ts.o


2、配置内核

System Type —>

[ ] ADC common driver support

Device Drivers —>

Input device support —>

[* ] Touchscreens —>

<*> EmbedSky TQ2440 TouchScreen input driver

配置完毕后,保存配置,然后编译内核,烧写镜像到开发板中,内核就能够支持触摸功能了。但是现在还没有移植QT,所以无法使用触摸功能,接下来配置一下QT。


3、文件系统中添加Qte

首先要制作带有Qte的文件系统,此处直接从天嵌科技提供的文件系统(rootfs_2.6.30.4 的文件系统)源码里面复制:“/opt/”目录和“/root/”目录到自己建立的文件系统里面,替换掉以前的目录。使用的qtopia 是 2.2.0 版本的。

然后再在文件系统的“/bin/”目录下面新建一个名为:“qtopia”的可执行文件,内容如下:


#!/bin/sh

echo Start Qtopia-2.2.0 > /dev/tq2440_serial0

if [ -f /etc/pointercal ] ; then

$QPEDIR/bin/qpe > /dev/null 2>/dev/null

else

ts_calibrate

$QPEDIR/bin/qpe > /dev/null 2>/dev/null

fi


添加可执行权限:


chmod  u+x  qtopia


修改“/etc/init.d/rcS”文件,下面列出新添加的内容:


PATH=/sbin:/bin:/usr/sbin:/usr/bin

runlevel=S

prevlevel=N

umask 022

export PATH runlevel prevlevel

#

#Trap CTRL-C &c only in this shell so we can interrupt subprocesses.

#

mount -a

mkdir /dev/pts

mount -t devpts devpts /dev/pts

echo /sbin/mdev > /proc/sys/kernel/hotplug

mdev -s

mkdir -p /var/lock

mkdir /dev/fb /dev/v4l

ln -s /dev/fb0 /dev/fb/0

ln -s /dev/video0 /dev/v4l/video0

ln -s /dev/ts0 /dev/h3600_tsraw #建立一个触摸设备的链接


export set TSLIB_TSDEVICE=/dev/event0

export set TSLIB_CONFFILE=/etc/ts.conf

export set TSLIB_PLUGINDIR=/lib/ts

export set TSLIB_CALIBFILE=/etc/pointercal

export set HOME=/root

export set QTDIR=/opt/Qtopia

export set QPEDIR=/opt/Qtopia

export set KDEDIR=/opt/kde

export set QWS_KEYBOARD="TTY:/dev/tty1"

export set QWS_MOUSE_PROTO="TPanel:/dev/event0 USB:/dev/mouse0"

export set PATH=$QPEDIR/bin: $PATH

export set LD_LIBRARY_PATH= $QTDIR/lib: $QPEDIR/lib


qtopia & #启动 Qte 的脚本,上面几行是设置 QT 的环境变量

/bin/hostname -F /etc/sysconfig/HOSTNAME


然后复制 tslib 的相关文件到新建的文件系统中:

复制“ts.conf”文件到新建的文件系统的“etc/”目录下,“ts.conf”文件的内容如下:

#Uncomment if you wish to use the linux input layer event interface

module_raw input

#Uncomment if you’re using a Sharp Zaurus SL-5500/SL-5000d

#module_raw collie

#Uncomment if you’re using a Sharp Zaurus SL-C700/C750/C760/C860

#module_raw corgi

#Uncomment if you’re using a device with a UCB1200/1300/1400 TS interface

#module_raw ucb1x00

#Uncomment if you’re using an HP iPaq h3600 or similar

#module_raw h3600

#Uncomment if you’re using a Hitachi Webpad

#module_raw mk712

#Uncomment if you’re using an IBM Arctic II

#module_raw arctic2

module pthres pmin=1

module variance delta=30

module dejitter delta=100

module linear


复制可执行程序“ts_calibrate”到新建的文件系统的“sbin/”目录下,这是触摸校正程序;

[1] [2]
关键字:嵌入式驱动  移植  触摸驱动 引用地址:嵌入式驱动移植之触摸驱动初识

上一篇:嵌入式驱动移植之声卡驱动移植
下一篇:LCD驱动移植之背光控制

小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved