編者:linux2.6.32并沒有帶S3C2440觸摸屏驅(qū)動(dòng)程序,需要自己實(shí)現(xiàn)。而在此的觸摸屏驅(qū)動(dòng)程序時(shí)作為一個(gè)輸入設(shè)備來實(shí)現(xiàn)的。在linux中,對(duì)于輸入設(shè)備而言,內(nèi)核專為其設(shè)計(jì)了輸入子系統(tǒng),由核心層處理公共的工作。因?yàn)閷?duì)于輸入設(shè)備而言,只是中斷、讀鍵值/坐標(biāo)值是與設(shè)備相關(guān)的,其余的如輸入事件的緩沖區(qū)的管理以及字符設(shè)備驅(qū)動(dòng)的file_operations接口則是輸入設(shè)備通用的。所以在此是在輸入子系統(tǒng)的框架下進(jìn)行編寫觸摸屏驅(qū)動(dòng)程序。對(duì)于這個(gè)驅(qū)動(dòng)的移植以及講解,參考了網(wǎng)上的一些文章,一部分摒棄了手冊(cè)。
1 在內(nèi)核中添加觸摸屏驅(qū)動(dòng)程序
Linux-2.6.32.2 內(nèi)核也沒有包含支持S3C2440 的觸摸屏驅(qū)動(dòng),因此我們自行設(shè)計(jì)了一個(gè)s3c2410_ts.c,它位于linux-src/drivers/input/touchscreen 目錄下,你可以自己增加一個(gè)s3c2410_ts.c 文件,并復(fù)制如下內(nèi)容:
#include 然后在linux-2.6.32.2/drivers/input/touchscreen/Makefile 文件中添加該源代碼的目標(biāo)模塊,如圖紅色部分: menuconfig INPUT_TOUCHSCREEN 至此,我們就已經(jīng)在內(nèi)核中添加完了觸摸屏驅(qū)動(dòng)。 2 配置編譯內(nèi)核并測(cè)試觸摸屏驅(qū)動(dòng) 3、觸摸屏驅(qū)動(dòng)程序的詳細(xì)分析。 這個(gè)內(nèi)容由于較多,放在下一個(gè)文章里,見下鏈接。 linux-2.6.32在mini2440開發(fā)板上移植(10)之觸摸屏工作原理以及驅(qū)動(dòng)程序詳細(xì)分析。 http://www.linuxidc.com/Linux/2013-04/82383p10.htm
#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 *s3c2410ts_name = 's3c2410 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 s3c2410_ts_connect(void)
{
s3c2410_gpio_cfgpin(S3C2410_GPG(12), S3C2410_GPG12_XMON);
s3c2410_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPG13_nXPON);
s3c2410_gpio_cfgpin(S3C2410_GPG(14), S3C2410_GPG14_YMON);
s3c2410_gpio_cfgpin(S3C2410_GPG(15), 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 s3c2410ts_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 */
s3c2410_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 = s3c2410ts_name;
dev->id.bustype = BUS_RS232;
dev->id.vendor = 0xDEAD;
dev->id.product = 0xBEEF;
dev->id.version = S3C2410TSVERSION;
/* Get irqs */
if (request_irq(IRQ_ADC, stylus_action, IRQF_SHARED|IRQF_SAMPLE_RANDOM,
's3c2410_action', dev)) {
printk(KERN_ERR 's3c2410_ts.c: Could not allocate ts IRQ_ADC !n');
iounmap(base_addr);
return -EIO;
}
if (request_irq(IRQ_TC, stylus_updown, IRQF_SAMPLE_RANDOM,
's3c2410_action', dev)) {
printk(KERN_ERR 's3c2410_ts.c: Could not allocate ts IRQ_TC !n');
iounmap(base_addr);
return -EIO;
}
printk(KERN_INFO '%s successfully loadedn', s3c2410ts_name);
/* All went ok, so register to the input system */
input_register_device(dev);
return 0;
}
static void __exit s3c2410ts_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(s3c2410ts_init);
module_exit(s3c2410ts_exit);
obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o
obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
再打開linux-2.6.32.2/drivers/input/touchscreen/Kconfig 文件,加入如下紅色部分,這樣就在內(nèi)核配置中添加了mini2440 的觸摸屏驅(qū)動(dòng)選項(xiàng):
bool 'Touchscreens'
help
Say Y here, and a list of supported touchscreens will be displayed.
This option doesn't affect the kernel.
If unsure, say Y.
if INPUT_TOUCHSCREEN
config TOUCHSCREEN_S3C2410
tristate 'Samsung S3C2410 touchscreen input driver'
depends on MACH_MINI2440 && INPUT && INPUT_TOUCHSCREEN && MINI2440_ADC
help
Say Y here if you have the s3c2410 touchscreen.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called s3c2410_ts.
config TOUCHSCREEN_ADS7846
tristate 'ADS7846/TSC2046 and ADS7843 based touchscreens'
depends on SPI_MASTER
depends on HWMON = n || HWMON
help
在命令行執(zhí)行:make menuconfig,然后依次選擇如下子菜單,找到剛剛添加的觸摸屏驅(qū)動(dòng)選項(xiàng):
Device Drivers --->
Input device support --->
[*] Touchscreens --->
按空格鍵選中觸摸屏驅(qū)動(dòng)配置選項(xiàng):退出并保存以上內(nèi)核配置,在命令行輸入:make zImage,將生成arch/arm/boot/zImage文件,使用supervivi 的“k”命令把它燒寫到開發(fā)板。在此我們還是使用缺省的文件系統(tǒng)root_qtopia,可以看到屏幕上出現(xiàn)校正界面:依照屏幕提示,使用觸摸筆逐步點(diǎn)擊“十”型交叉點(diǎn),即可進(jìn)入qtopia 系統(tǒng)。
上一篇:linux-2.6.32在mini2440開發(fā)板上移植 添加ADC驅(qū)動(dòng)程序
下一篇:linux-2.6.32在mini2440開發(fā)板上移植-觸摸屏工作原理以及驅(qū)動(dòng)程序詳細(xì)分析
推薦閱讀最新更新時(shí)間:2025-04-24 12:22



設(shè)計(jì)資源 培訓(xùn) 開發(fā)板 精華推薦
- 英飛凌微控制器:以全新實(shí)惠套件和強(qiáng)大開發(fā)環(huán)境為開發(fā)者提供支持
- iTOP-i.MX6開發(fā)板設(shè)備數(shù)驅(qū)動(dòng)Menuconfig的用法
- 迅為IMX6ULL開發(fā)板Qt for Android搭建開發(fā)環(huán)境
- 迅為i.MX8M mini開發(fā)板Windots QT系統(tǒng)開發(fā)環(huán)境搭建
- 迅為IMX8MM開發(fā)板Yocto系統(tǒng)使用Gstarwmra(一)
- 迅為IMX8M mini開發(fā)板Linix系統(tǒng)修改默認(rèn)屏幕
- iTOP-4412開發(fā)板支持4G以上文件系統(tǒng)擴(kuò)展
- 迅為IMX8MM開發(fā)板Yocto系統(tǒng)設(shè)置開機(jī)自啟動(dòng)
- 迅為IMX6Q開發(fā)板 Buildroot文件系統(tǒng)mqtt測(cè)試
- 2.13寸微雪電子墨水屏驅(qū)動(dòng)板
- IRSM808-105MH 小家電電機(jī)驅(qū)動(dòng)應(yīng)用半橋IPM典型應(yīng)用電路
- 32愛心板
- 【電賽】 接線轉(zhuǎn)接板
- AM2DM-1212DH60-NZ ±12 Vout、2W 雙路輸出 DC-DC 轉(zhuǎn)換器的典型應(yīng)用
- MC33074DTBR2G快速建立逆變器的典型應(yīng)用
- DC678A,用于 LT5517EUF、40MHz 至 900MHz 直接轉(zhuǎn)換正交解調(diào)器的演示板
- Arduino2560 I/O擴(kuò)展板
- NCS21911SN2GEVB:NCS21911SN 評(píng)估板
- 【RA】基于瑞薩RA2E1的律動(dòng)燈條+1437350A
- Vishay 推出的27款600 V標(biāo)準(zhǔn)整流器和60 V - 200 V TMBS?整流器
- 泰克亮相2025 慕尼黑展: 以全棧式解決方案與中國智造同頻共振
- Nordic Semiconductor nRF9151 蜂窩物聯(lián)網(wǎng)模組與日本 IIJ SoftSIM產(chǎn)品相輔相成
- 汽車顯示屏——第2部分:TFT LCD、OLED和micro-LED顯示屏電源技術(shù)
- 車機(jī)操作系統(tǒng)自主可控加速!華為、小米和理想,誰是真正的領(lǐng)跑者?
- FOC入門教程
- 如何為工業(yè)物聯(lián)網(wǎng)選擇最節(jié)能的通信方案
- 什么是PID算法?一文帶你深度理解PID算法
- 控制無刷直流電動(dòng)機(jī)以應(yīng)對(duì)新挑戰(zhàn)
- 汽車加熱器的工作原理和功能
- ADI有獎(jiǎng)下載活動(dòng)之23:ADI民用無人機(jī)解決方案
- 是德科技白皮書下載:攻克當(dāng)前面臨的毫米波測(cè)試難關(guān)
- MPS電機(jī)研究院 讓電機(jī)更聽話的秘密! 第一站:電機(jī)應(yīng)用知識(shí)大考!
- 有獎(jiǎng)直播:是德科技高速芯片設(shè)計(jì)新技術(shù)研討會(huì)
- Altera Cyclone V 開發(fā)板全體驗(yàn)
- 借助 Microchip 生態(tài)系統(tǒng)中的 PIC® 和 AVR® 單片機(jī)開啟嵌入式到云端之旅 系列在線研討會(huì)
- Microchip直播|如何在ADAS系統(tǒng)中解決精密授時(shí)挑戰(zhàn)
- 2009 EEWORLD 年度人物大評(píng)選活動(dòng)評(píng)獎(jiǎng)揭曉
- 碎片化的IoT時(shí)代,中天微填補(bǔ)國產(chǎn)嵌入式CPU空白
- 預(yù)裝Android8.1 中興新機(jī)入網(wǎng)工信部
- 小屏幕手機(jī)愛好者福音 新版iPhone SE曝光:支持無線充電
- 兆易GD32 MCU再度包攬2018年中國IC設(shè)計(jì)成就獎(jiǎng)多項(xiàng)大獎(jiǎng)
- 臺(tái)積電第四季7nm營收可占七成
- Vishay推出新型汽車級(jí)IHLP?電感,工作溫度可達(dá)+155 °C
- 基于LabVIEW的電機(jī)壽命測(cè)試控制系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)
- Spectrum多通道任意波形發(fā)生器顯著降低信號(hào)生成成本
- LabVIEW機(jī)器人模塊――機(jī)器人選板中的特殊算法和API
- 利用LabVIEW Multisim連接工具包(?版)實(shí)現(xiàn)Multisim自動(dòng)化簡介