开发环境
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/”目录下,这是触摸校正程序;
上一篇:嵌入式驱动移植之声卡驱动移植
下一篇:LCD驱动移植之背光控制
设计资源 培训 开发板 精华推荐
- STEVAL-IHT008V1,具有浪涌电流限制和绝缘交流开关控制的低待机损耗前端评估板
- 使用 Microchip Technology 的 MIC45116-1YMP 的参考设计
- 使用 ON Semiconductor 的 NCP4302 的参考设计
- 基于MCU的本地语音控制解决方案
- LTM4622EY 3.3Vin、1.5V 和 1.2V 输出、2.5A 设计的典型应用电路,具有输出一致跟踪功能
- BFP420 晶体管作为低成本 900 MHz ISM 频段功率放大器
- USB2UART
- 18b20
- NSIC2030JBT3G 恒流单灯串典型应用
- AD8314ACP-EVALZ,AD8314 评估板,100MHz 至 2.7GHz,45dB 射频检波器/控制器