新手问一个触摸屏驱动中关于中断的问题
最近在弄触摸屏的驱动,但发现一些基本的问题还没有弄明白:
1.在中断服务程序中,需要直接操作S3C2410_INTMSK等寄存器吗?以前弄按键驱动的时候好像没处理,中断发生正常!为什么?(在裸机的程序中是要往对应位写1的啊!)
2:现在在弄的触摸屏驱动,中断可以注册,cat /proc/interrupt 里也有相关中断信息。但程序进不了中断。
这是为什么? 还有那些地方要设置吗?(看到一些程序中,要开ADC模块的时钟。现在需要吗?)
麻烦高手们,帮我想一想。我实在不知道怎么解决了! 谢谢!
[ 本帖最后由 vincent_zs 于 2009-3-23 21:35 编辑 ]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
在线等啊~~~~~~~~~~~
半年没摸ARM了 = =
忘记得差不多了 Orz 不好意思~
有一个UPDOWN 的位,你设置为抬起的话也不会进入中断,
边缘触发中断?
具体是先检测down的中断 ,然后进入中断,再开始AD转换
转换完成。就可以读值了。也可以在AD转换完成后,再检测个up的中断
当做是松手检测。
今晚又抽空,调了一下程序,现在的情况是:还没有注册中断,中断就发生了!
另外可能寄存器的设置还有点问题。
在有的程序中,是用input子系统写的这个驱动程序的,但我还是想用简单的纯字符设备驱动的思路来写这个程序。 有做过这个的朋友,帮帮小弟好吗?
最近比较忙,只能慢慢的抽时间琢磨这个了 .......呼呼~~~~~
[ 本帖最后由 vincent_zs 于 2009-3-23 21:34 编辑 ]
注册中断之前应该关闭中断吧
我以前写了个,已经测试过了,可以用
/*
* main.c -- the bare test char module
*
* Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet
* Copyright (C) 2001 O'Reilly & Associates
*
* The source code in this file can be freely used, adapted,
* and redistributed in source or binary form, so long as an
* acknowledgment appears in derived source files. The citation
* should list that the code comes from the book "Linux Device
* Drivers" by Alessandro Rubini and Jonathan Corbet, published
* by O'Reilly & Associates. No warranty is attached;
* we cannot take responsibility for errors or fitness for use.
*
*/
//#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/interrupt.h> // tasklet
#include <linux/kernel.h> /* printk() */
#include <linux/slab.h> /* kmalloc() */
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t */
#include <linux/proc_fs.h>
#include <linux/fcntl.h> /* O_ACCMODE */
#include <linux/seq_file.h>
#include <linux/cdev.h>
#include <linux/poll.h>
//#include <linux/sp__raw_readlock.h>
#include <linux/delay.h>
#include <linux/sched.h> // wait_event_interruptible, wake_up_interruptible
#include <asm/semaphore.h>
#include <asm/system.h> /* cli(), *_flags */
#include <asm/uaccess.h> /* copy_*_user */
#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/arch/uncompress.h>
#include <asm/arch/regs-adc.h>
#include <asm/arch/regs-gpio.h>
int test_major = 220;
int test_minor = 0;
int test_nr_devs = 1; /* number of bare test devices */
static struct cdev *test_devices;
static struct semaphore sem;
static wait_queue_head_t mywait;
module_param(test_major, int, S_IRUGO);
module_param(test_minor, int, S_IRUGO);
module_param(test_nr_devs, int, S_IRUGO);
MODULE_AUTHOR("Alessandro Rubini, Jonathan Corbet";
MODULE_LICENSE("Dual BSD/GPL";
void __iomem * base_addr;
#define WAIT4INT(x) (((x)<< | 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))
#define AD_COUNT 5
unsigned int Gabs[AD_COUNT];
unsigned long xp;
unsigned long yp;
void Startad(void)
{
writel((S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST), base_addr+S3C2410_ADCTSC);
writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
printk("<1> start ad conveting\n";
}
irqreturn_t stylus_updown(int irq,void * dev_id,struct pt_regs * regs)
{
int temp_updown;
temp_updown=__raw_readl(base_addr+S3C2410_ADCDAT0)&(1<<15);
if (temp_updown==0) // stylus down
{
printk("<1>the stylus is down,state=%d\n",temp_updown);
Startad();
}
else
{
printk("<1>the stylus is up,state=%d\n",temp_updown);
writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
}
printk("<1> in interrupt\n";
return IRQ_HANDLED;
}
irqreturn_t ad_action(int irq,void * dev_id,struct pt_regs * regs)
{
unsigned long data0;
unsigned long data1;
static char counter=0; // AD计算次数
data0 = readl(base_addr+S3C2410_ADCDAT0);
data1 = readl(base_addr+S3C2410_ADCDAT1);
counter++;
xp+=(data1&0x3ff);
yp+=(data0&0x3ff);
if (counter>AD_COUNT)
{
xp=xp/AD_COUNT;
yp=yp/AD_COUNT;
writel(WAIT4INT(1), base_addr+S3C2410_ADCTSC);
printk("<1> xp_average=%d,yp_average=%d,counter=%d\n",xp,yp,counter);
counter=0;
xp=0;
yp=0;
return IRQ_HANDLED;
}
printk("<1> xp=%d,yp=%d,\n",xp,yp);
Startad();
return IRQ_HANDLED;
}
int test_open(struct inode *inode, struct file *filp)
{
struct clk *clk;
clk=clk_get(NULL,"adc";
if(IS_ERR(clk)) panic("error to get adc clock\n";
clk_enable(clk);
try_module_get(THIS_MODULE);
printk(KERN_EMERG"device opening\n";
s3c2410_gpio_cfgpin(S3C2410_GPF4,S3C2410_GPIO_OUTPUT); // LED
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);
base_addr=ioremap(S3C2410_PA_ADC,0X100);
if (base_addr == NULL) {
printk(KERN_ERR "Failed to remap register block\n";
return -ENOMEM;
}
__raw_writel(1<<14|55<<6,base_addr+S3C2410_ADCCON); // prescale
__raw_writel(20000,base_addr+S3C2410_ADCDLY); // adcdly
writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC); // 设置updown=0,等待触摸笔点击状态
printk(KERN_EMERG"device opening over \n";
return 0; /* success */
}
int test_release(struct inode *inode, struct file *filp)
{
module_put(THIS_MODULE);
iounmap(base_addr);
printk(KERN_EMERG"device closeing now\n";
return 0;
}
/*
* Follow the list
*/
ssize_t test_read(struct file *filp, int __user *buf, size_t count,
loff_t *f_pos)
{
ssize_t retval = 0;
char b[5]={0};
if (down_interruptible(&sem))
return -ERESTARTSYS;
/*
if (copy_to_user(buf, &test_value, sizeof(test_value))) {
retval = -EFAULT;
printk("<1> read error");
goto out;
}
*/
retval = count;
printk(KERN_EMERG"device reading\n,b[0]=%d,b[1]=%d\n",b[0],b[1]);
out:
up(&sem);
return retval;
}
struct file_operations test_fops = {
.owner = THIS_MODULE,
.read = test_read,
.open = test_open,
.release = test_release,
};
/*
* Finally, the module stuff
*/
/*
* The cleanup function is used to handle initialization failures as well.
* Thefore, it must be careful to work correctly even if some of the items
* have not been initialized
*/
void test_cleanup_module(void)
{
dev_t devno = MKDEV(test_major, test_minor);
if (test_devices) {
cdev_del(test_devices);
}
free_irq(IRQ_TC,NULL);
free_irq(IRQ_ADC,NULL);
unregister_chrdev_region(devno, 1);
}
/*
* Set up the char_dev structure for this device.
*/
static void test_setup_cdev(struct cdev *dev, int index)
{
int err, devno = MKDEV(test_major, test_minor + index);
dev=cdev_alloc();
cdev_init(dev, &test_fops);
dev->owner = THIS_MODULE;
dev->ops = &test_fops;
err = cdev_add (dev, devno, 1);
if (err)
printk(KERN_NOTICE "Error %d adding test%d", err, index);
}
int test_init_module(void)
{
int result;
dev_t dev = 0;
if (test_major)
{
dev = MKDEV (test_major,test_minor);
result = register_chrdev_region(dev, 1, "test");
}
else
{
result = alloc_chrdev_region(&dev, test_minor, 1,
"test");
test_major = MAJOR(dev);
}
if (result < 0) {
printk(KERN_WARNING "test: can't get major %d\n", test_major);
return result;
}
init_MUTEX(&sem);
test_setup_cdev(test_devices, 0);
init_waitqueue_head(&mywait);
/* At this point call the init function for any friend device */
dev = MKDEV(test_major, test_minor);
printk("<1>hello,i am coming\n");
if (request_irq(IRQ_ADC, ad_action,IRQF_SAMPLE_RANDOM, "s3c2410_action", NULL))
{
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", NULL))
{
printk(KERN_ERR "s3c2410_ts.c: Could not allocate ts IRQ_TC !\n");
iounmap(base_addr);
return -EIO;
}
return 0; /* succeed */
fail:
test_cleanup_module();
return result;
}
module_init(test_init_module);
module_exit(test_cleanup_module);
感谢LS的前辈,这正是我想要的!
看了下整个程序,思路和我的差不多。 太感谢了。 拿你的代码我再去琢磨琢磨。
一定要找到出错的原因!也感谢上面所有回帖的朋友们。thanks